How to make a NTML request with Alamofire 4.0?

好久不见. 提交于 2019-12-11 02:58:25

问题


These are request headers:

    let headers: HTTPHeaders = [
        "Accept": "application/json",
        "username": "someUserName",
        "password": "aPasswordForSomeUserName"
    ]

When making a request with below code it's giving me "Garbage at the end". However, when I checked the response with JSON parser online. It's a valid JSON.

Alamofire.request("http://myserver/list.svc/random", headers: headers).responseJSON { response in
    print(response)
}

I also tried making a request like this:

Alamofire.request("http://myserver/list.svc/random", headers: headers).responseString { response in
    print(response)
}

I am getting this message in console: "401 UNAUTHORIZED".

What am I doing wrong? I believe, when using responseJSON completion block it's not complaining about Unauthorization, but it's complaining about bad JSON (or some garbage).

P.S. The same request works fine with Advance Rest Client (a chrome extension) and also in chrome browser.


回答1:


I don't know how relevant this is to you anymore but I've got a working solution I'll post for any future reference.

So, I had two issues. The first one being that the Authorization header fell of the request when it was redirected. The second one being the NTLM-challenge from the server not being handled. The following code should be quite self explanatory I hope :) It asumes you store the username and password in variables name just that.

    let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8)!
    let base64Credentials = credentialData.base64EncodedString(options: [])
    request.addValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")

    let manager = Alamofire.SessionManager.default
    let delegate: Alamofire.SessionDelegate = manager.delegate

    // This bit will re-add the auth headers for the redirected request
    delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
        var redirectedRequest = request

        if let originalRequest = task.originalRequest, let redirectheaders = originalRequest.allHTTPHeaderFields {
            if let authorizationHeaderValue = redirectheaders["Authorization"] {
                redirectedRequest.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
            }
            if let contentTypeHeaderValue = redirectheaders["Content-Type"] {
                redirectedRequest.setValue(contentTypeHeaderValue, forHTTPHeaderField: "Content-Type")
            }
        }

        return redirectedRequest
    }

    // This bit looks at challenges received and applies the correct credentials
    delegate.taskDidReceiveChallenge = { session, task, challenge in
        var disposition: URLSession.AuthChallengeDisposition = .useCredential
        var credential: URLCredential = URLCredential()

        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM) {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(user: username, password: password, persistence: URLCredential.Persistence.forSession)
        }

        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        }

        return(disposition, credential)
    }

    manager.request(request).responseData { (response) in
        // Handle response accordingly
    }

Hope this helps someone.




回答2:


In Swift4.2

Alamofire has built in NTLM auth support. You can make a request like that

        let user = "YOUR_USER_NAME OR EMAIL"
        let password = "YOUR_PASSWORD"
        let url = "YOUR_API_URL"
        let credential = URLCredential(user: user, password: password, persistence: .forSession)
        //These headers are optional based on your api and your server.
        //There were required for me
        let headers = ["Accept": "application/json;odata=verbose",
                           "Content-type": "application/json;odata=verbose"]
        Alamofire.request(url, method: .get, headers: headers).authenticate(usingCredential: credential).responseJSON {
                (response) in
                switch response.result {
                case .success:
                    if let value = response.result.value {
                        print("The server response is: ", value)
                    }else{
                        print("There is error in the server response")
                    }
                case .failure (let error):
                    print("The NTLM request error is: ", error.localizedDescription)
                }

            }


来源:https://stackoverflow.com/questions/45912367/how-to-make-a-ntml-request-with-alamofire-4-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!