使用Alamofire进行基本身份验证

25

在使用基本身份验证时遇到了问题。我正在使用符合URLRequestConvertible协议的标准枚举来构造我的请求。问题是,当我像这样手动设置枚举中的授权标头时:

    let user = ***
    let password = ***

    let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
    let base64Credentials = credentialData.base64EncodedStringWithOptions([])

    mutableURLRequest.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")

我总是得到401未授权的响应。然而,如果我像这样使用authenticate回调函数设置密码:

    Alamofire.request(request)
        .authenticate(user: "USERNAME_HERE", password: "PASSWORD_HERE")
        .responseJSON { (response) -> Void in
            print("JSON response \(response)")
            completion(success: true, error: nil)
    }

它已经成功验证。我希望能够在符合URLRequestConvertible枚举中手动设置它,而不是在authenticate中传递凭据。

我知道它在身份验证挑战下使用NSURLCredential,但我希望能够手动设置它。

这是我的URLRequestConvertible实现:

enum CheckedUpAPI: URLRequestConvertible {
    static let baseURLString = "https://***"
    static let APIKey = "***"
    static let APIClientName  = "iPad"


    case UpdatePatient(String, [String: AnyObject])


    var method: Alamofire.Method {
        switch self {
        case .UpdatePatient:
            return .PATCH
        }
    }

    var path: String {
        switch self {
        case .UpdatePatient(let patientID, _):
            return "patients/\(patientID)"
        }
    }

    // MARK: URLRequestConvertible

    var URLRequest: NSMutableURLRequest {
        let URL = NSURL(string: CheckedUpAPI.baseURLString)!
        let mutableURLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(path))
        mutableURLRequest.HTTPMethod = method.rawValue


/**
        We are not setting any authorization headers since they requests return 401
        the `authenticate` function on Alamofire.request does the trick

        let user = "easy@test.com"
        let password = "test"

        let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
        let base64Credentials = credentialData.base64EncodedStringWithOptions([])

        mutableURLRequest.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")
*/
        mutableURLRequest.setValue(CheckedUpAPI.APIKey, forHTTPHeaderField: "API-Key")

        switch self {
        case .UpdatePatient(_, let parameters):
            return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
        }
    }
}

иҜ·еҲҶдә«жӮЁеҰӮдҪ•дҪҝз”ЁAlamofireзҡ„mutableURLRequestеӨҙйғЁжқҘеҸ‘еҮәиҜ·жұӮгҖӮ - Victor Sigler
@VictorSigler 已完成。手动设置标头已被注释掉,因为它从未起作用。但这就是我尝试过的,当使用Alamofireauthenticate函数时它不起作用。 - Walter Martin Vargas-Pena
@VictorSigler 有什么想法吗? - Walter Martin Vargas-Pena
6个回答

35

在 Swift 3.0 中

请使用以下代码 -

    let user = ***
    let password = ***
    let credentialData = "\(user):\(password)".data(using: String.Encoding.utf8)!
    let base64Credentials = credentialData.base64EncodedString(options: [])
    let headers = ["Authorization": "Basic \(base64Credentials)"]

    Alamofire.request(customerURL,
                      method: .get,
                      parameters: nil,
                      encoding: URLEncoding.default,
                      headers:headers)
        .validate()
        .responseJSON { response in
            if response.result.value != nil{                    
               print(response)
            }else{

            }
    }

27
Alamofire.request(urlString, method: .get).authenticate(user: "username", password: "pwd").responseJSON

只需要进行身份验证


2
这个答案太简单了:D - Sven Driemecker

21

你可以尝试这段代码:

    let user = ***
    let password = ***
    let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
    let base64Credentials = credentialData.base64EncodedStringWithOptions([])
    let headers = ["Authorization": "Basic \(base64Credentials)"]

Alamofire.manager.request(.GET, stringURL,headers: headers, parameters: params as? [String : AnyObject])
        .responseJSON { response  in
            if (response.result.error == nil){
                success(data: response.result.value)
            }else{
                fail(error: response.result.error)
            }
    }

感谢耶稣,它帮了我很多。 - Dara Tith
感谢您的回复。这个方法可以行得通,但是它会在我的代码中到处都是这个。我正在尝试将所有网络相关的内容保持在URLRequestConvertible实现中分离出来。 - Walter Martin Vargas-Pena
请告诉我在上面的代码中我应该在哪里添加我的证书路径?在我的情况下,我的证书属于NSBundle文件夹...如果您知道,请帮助我。 - Dipen Chudasama

8

Swift 4

private func getHeaders() -> [String: String] {
        let userName = "xxxx"
        let password = "xxxx"
        let credentialData = "\(userName):\(password)".data(using: .utf8)
        guard let cred = credentialData else { return ["" : ""] }
        let base64Credentials = cred.base64EncodedData(options: [])
        guard let base64Date = Data(base64Encoded: base64Credentials) else { return ["" : ""] }
        return ["Authorization": "Basic \(base64Date.base64EncodedString())"]
    }

当您直接设置Authorization标头时,iOS可能不会发送它。请参见https://developer.apple.com/documentation/foundation/nsurlrequest - Dielson Sales

4
Alamofire提供了比手动创建标头更简单的方法。
以下是“ Basic Auth” 部分相关的代码片段,可在此处找到:
  manager.request(.GET, "https://api.parse.com/1/classes/Spot/")
    .authenticate(user: username, password: password)
    .responseSpotsArray { response in
      completionHandler(response.result)
    }

1

最终找到了问题所在。原来是URL中缺少一个斜杠。似乎Alamofire不能像AFNetworking一样处理它。通过记录请求并查看实际请求中缺少一些字节,我能够找到问题所在。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接