如何使用 Alamofire 连接本地主机(证书无效)?

How to Connect localhost (with invalid certificate) using Alamofire?

这是我使用 swift 的第一个项目。我正在使用 alamofire 连接 API。我有一个 API 的本地副本,我想用于调试 - 所以我可以设置测试数据 - 因为远程 API 已经有了我不能乱用的真实数据。

问题是当我尝试访问 https://localhost:8443/MyProject

时出现以下错误

Optional(Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk." UserInfo=0x7fbeb8c61ff0 {NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9813, NSUnderlyingError=0x7fbeb8ea5c00 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1202.)", NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk., NSErrorFailingURLKey=https://localhost:8443/myproject/api/loginUser.pdo, NSErrorFailingURLStringKey=https://localhost:8443/myproject/api/loginUser.pdo, _kCFStreamErrorDomainKey=3})

我已经找到了很多解决方案,其中大部分是针对 Objective-c 的,例如使用 setAllowsAnyHTTPSCertificate 或使用委托进行连接。 但是我在 swift 中找不到 setAllowsAnyHTTPSCertificate 的等价方法,而且我不确定在使用 alamofire 时如何将委托设置为连接。 我有什么想法吗?

提前致谢。

您可以使用 SessionDelegate 覆盖闭包轻松覆盖 Alamofire 中的默认质询行为。以下是如何允许 Alamofire 接受无效证书的示例:

IMPORTANT: Please do not use this in any production code. Security is VERY important and this implementation completely disregards the security mechanisms in Alamofire. Use at your own risk!

let manager = Alamofire.Manager.sharedInstance

manager.delegate.sessionDidReceiveChallenge = { session, challenge in
    var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
    var credential: NSURLCredential?

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
        disposition = NSURLSessionAuthChallengeDisposition.UseCredential
        credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
    } else {
        if challenge.previousFailureCount > 0 {
            disposition = .CancelAuthenticationChallenge
        } else {
            credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)

            if credential != nil {
                disposition = .UseCredential
            }
        }
    }

    return (disposition, credential)
}

我们(Alamofire TC) are going to implement TLS pinning and several other features related to security in the Alamofire 1.3.0发布。


更新

Alamofire 1.3.0 版本已经发布,并为自定义服务器信任身份验证挑战添加了更好的支持。有关详细信息,请查看自述文件的 Security 部分。

Swift @cnoon 代码的 3 版本

    manager.delegate.sessionDidReceiveChallenge = { session, challenge in
        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
        var credential: URLCredential?

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let trust = challenge.protectionSpace.serverTrust {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: trust)
        } else {
            if challenge.previousFailureCount > 0 {
                disposition = .cancelAuthenticationChallenge
            } else {
                credential = self.manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                if credential != nil {
                    disposition = .useCredential
                }
            }
        }

        return (disposition, credential)
    }

将 https 替换为我的基地 url 的 http。解决了错误。

Swift 3

就我而言,当我使用 swagger 客户端库时,我更改了代码以像这样测试本地服务器:

 open func createSessionManager() -> Alamofire.SessionManager {
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = buildHeaders()

    let serverTrustPolicies: [String: ServerTrustPolicy] = ["localhost": .disableEvaluation]

    return Alamofire.SessionManager(configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
}