无法使用 Alamofire 4.5 在本地连接到自签名证书保护的 Nginx

Posted

技术标签:

【中文标题】无法使用 Alamofire 4.5 在本地连接到自签名证书保护的 Nginx【英文标题】:Cannot connect locally to self-signed cert protected Nginx using Alamofire 4.5 【发布时间】:2017-10-27 15:10:11 【问题描述】:

我正在使用 Alamofire 4.5 和 XCode 9.0.1。我无法连接到配置了自签名证书的本地 nginx

根据this answer,我正在使用以下代码:

private static var Manager : Alamofire.SessionManager = 
    // Create the server trust policies
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "localhost:8443": .disableEvaluation
    ]
    // Create custom manager
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let man = Alamofire.SessionManager(
        configuration: URLSessionConfiguration.default,
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )
    return man
()

然后像这样拨打电话:

DataService.Manager.request("https://localhost:8443/foo", parameters: parameters).validate().responseJSON

我在项目中尝试了各种配置,但都无济于事:

这是我看到的错误:

2017-10-27 08:59:17.118751-0600 hptest[53607:8423753] TIC SSL Trust 
Error [1:0x60400016e580]: 3:0
2017-10-27 08:59:17.119020-0600 hptest[53607:8423753] 
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, 
-9813)
2017-10-27 08:59:17.119111-0600 hptest[53607:8423753] Task <A8A3F1A4-
D6A5-4AD6-9C3F-23697D8B63AD>.<1> HTTP load failed (error code: -1202 

[3:-9813])
2017-10-27 08:59:17.119281-0600 hptest[53607:8423742] Task <A8A3F1A4-D6A5-4AD6-9C3F-23697D8B63AD>.<1> finished with error - code: -1202
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=NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000001149a0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, NSErrorPeerCertificateChainKey=(
    "<cert(0x7fc41b870000) s: localhost i: localhost>"
), NSUnderlyingError=0x60800005f980 Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo=_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000001149a0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x7fc41b870000) s: localhost i: localhost>"
), 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/foo, NSErrorFailingURLStringKey=https://localhost:8443/foo, NSErrorClientCertificateStateKey=0

【问题讨论】:

【参考方案1】:

我设法用会话管理器的以下代码解决了这个问题——应该首先使用 RTFM 而不是 SO:

private static var Manager : Alamofire.SessionManager = 
    // Create the server trust policies
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "localhost:8443": .disableEvaluation
    ]
    // Create custom manager
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let man = Alamofire.SessionManager(
        configuration: URLSessionConfiguration.default,
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )

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

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust 
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
         else 
            if challenge.previousFailureCount > 0 
                disposition = .cancelAuthenticationChallenge
             else 
                credential = man.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                if credential != nil 
                    disposition = .useCredential
                
            
        

        return (disposition, credential)
    

    return man
()

【讨论】:

以上是关于无法使用 Alamofire 4.5 在本地连接到自签名证书保护的 Nginx的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Alamofire 访问具有无效证书的本地 Https?

无法使用 JDBC 连接到 docker 中的本地 MySQL

无法在本地环境中使用 docker 连接到 cakephp 中的 mysql 数据库

无法在 Windows 机器上使用 sqlalchemy 连接到本地 mysql 数据库

无法使用 DBeaver 连接到本地主机上的 MariaDB

在 Windows 中无法连接到本地主机