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

时间:2017-10-27 15:10:11

标签: xcode nginx alamofire self-signed

我正在使用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

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

Xcode info configuration for security

以下是我看到的错误:

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 个答案:

答案 0 :(得分:0)

我设法使用以下代码管理器解决它 - 首先应该使用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
}()