首页 > 解决方案 > Alamofire https 请求仅在 NSExceptionAllowsInsecureHTTPLoads 设置为 true 时有效

问题描述

我在 Xcode10 中使用 Swift 开发了一个应用程序(应用程序名称:“TerminalsPOC”)。我正在使用 Alamofire向我的组织的内部 Web api 发出 https 请求(让我们将 URL 称为“ https://example.com:50001/RESTAdapter/toolbox/getMyData ”)。我有一个带有类级变量的类来引用会话管理器:

// Swift code
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        “example.com": .pinCertificates(
            certificates: ServerTrustPolicy.certificates(in: Bundle(for: type(of: self))),
            validateCertificateChain: false,
            validateHost: true
        )
    ]

     sessionManager = SessionManager(
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )

    sessionManager.request(url, method: .get) ... 

我已将必要的 .cer 证书导入到应用程序包中。我保留了默认的 ATS 设置,但添加了一个 NSExceptionDomain。相关的 info.plist 部分看起来像

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <false/>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>

只要将 NSExceptionAllowsInsecureHTTPLoads 设置设置为 true,它就可以工作。如果我将其设置为 false,则请求将失败并显示以下消息:发生 SSL 错误并且无法与服务器建立安全连接。[-1200]

2018-12-07 11:55:42.122423-0700 TerminalsPOC[27191:371810] ATS 系统信任失败 2018-12-07 11:55:42.122530-0700 TerminalsPOC[27191:371810] [2:0x600001fad740] 系统信任失败

2018-12-07 11:55:42.122637-0700 终端 POC [27191:371810] TIC SSL 信任错误 [2:0x600001fad740]: 3:0

2018-12-07 11:55:42.125928-0700 TerminalsPOC[27191:371810] NSURLSession/NSURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9802)

2018-12-07 11:55:42.126109-0700 TerminalsPOC[27191:371810] 任务 <54567E3C-2BBC-4227-9C0A-FC60370A10AA>.<1> HTTP 加载失败(错误代码:-1200 [3:-9802])

2018-12-07 11:55:42.126872-0700 TerminalsPOC[27191:371812] 任务 <54567E3C-2BBC-4227-9C0A-FC60370A10AA>.<1> 完成错误 - 代码:-1200

2018-12-07 11:55:42.140600-0700 TerminalsPOC[27191:371810] 任务 <54567E3C-2BBC-4227-9C0A-FC60370A10AA>.<1> 加载失败并出现错误 Error Domain=NSURLErrorDomain Code=-1200“SSL 错误已发生,无法与服务器建立安全连接。” UserInfo={NSLocalizedRecoverySuggestion=您还是要连接到服务器吗?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=( "", "" ), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey= https://example.com:50001/RESTAdapter/toolbox/ getMyData, NSErrorFailingURLStringKey= https://example.com:50001/RESTAdapter/toolbox/getMyData, NSUnderlyingError=0x6000024e89f0 {错误域=kCFErrorDomainCFNetwork 代码=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamErrorCodeKey=-9802, )}}, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <54567E3C-2BBC-4227-9C0A-FC60370A10AA>.<1>" ), _kCFStreamErrorCodeKey=-9802, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <54567E3C-2BBC-4227-9C0A-FC60370A1.<1> , NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedDescription=发生 SSL 错误,无法与服务器建立安全连接。} [-1200]

我尝试运行“nscurl --ats-diagnostics https://example.com:50001/RESTAdapter/toolbox/getMyData ”,响应包括以下内容:

默认 ATS 安全连接

--- ATS 默认连接结果:PASS

========

允许任意负载

--- 允许所有负载结果:通过

========= 为 example.com 配置 TLS 例外

--- TLSv1.3 2018-12-07 10:59:17.492 nscurl[24303:331847] NSURLSession/NSURLConnection HTTP 加载失败

(kCFStreamErrorDomainSSL, -9800) 结果:失败

--- TLSv1.2 结果:通过

--- TLSv1.1 结果:通过

--- TLSv1.0 结果:通过

============ 为 example.com 配置 PFS 例外

--- 禁用完美前向保密结果:通过

========== 为 example.com 配置 PFS 异常并允许不安全的 HTTP

--- 禁用完美前向保密并允许不安全的 HTTP 结果:通过

这一切对我来说都很好。我肯定错过了什么。

所以我的问题是:

1. 为什么将 NSExceptionAllowsInsecureHTTPLoads 设置为 true 会导致调用工作,因为它是一个 https 请求(没有重定向)?我认为这个设置只影响 http 调用,不应该影响 https 调用。

2. 如何在不设置 NSExceptionAllowsInsecureHTTPLoads 的情况下让这个 Web 请求工作(这似乎是一种 hack/work-around,不是吗)?

标签: swiftxcodesslalamofireapp-transport-security

解决方案


在这种情况下,问题是该应用程序在尚未安装所需证书的模拟器上运行。

一旦安装并信任了正确的(根)证书,固定证书检查就通过了,然后可以将NSExceptionAllowsInsecureHTTPLoadsinfo.plist 设置设置回“NO”。

我希望错误消息更明确。:-/


推荐阅读