【问题标题】:NSRequiresCertificateTransparency = YES makes https fail in iOS 9 simulatorNSRequiresCertificateTransparency = YES 使 https 在 iOS 9 模拟器中失败
【发布时间】:2017-06-14 09:35:33
【问题描述】:

我正在尝试为我的 ios 应用启用 App Transport Security 中的 NSRequiresCertificateTransparency 标志,以实现更好的安全性。我进行了测试,它在我的装有 iOS 10 的设备和装有 iOS 10 的模拟器上运行良好。但它使 https 连接在装有 iOS 9.3 的模拟器中失败。如果我只是关闭这个特定的标志,它就会再次工作。

问题不在我连接的服务器上,因为即使使用 www.apple.com 也能重现它。这是我使用的 Info.plist 中的设置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>www.apple.com</key>
        <dict>
            <key>NSRequiresCertificateTransparency</key>
            <true/>
        </dict>
    </dict>
</dict>

这里是代码:

NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://www.apple.com/"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error) {
        NSLog(@"fail");
    }
}];
[task resume];

我在日志中看到的错误是: NSURLSession/NSURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9802)

也许它只发生在 iOS 9 的模拟器中?不幸的是,我手头没有装有 iOS 9 的设备来测试它。

更新:

设置 CFNETWORK_DIAGNOSTICS=3 环境变量后,我在日志中看不到任何有用的信息。这是关于错误的部分:

    Response Error
    Request: <CFURLRequest 0x7f8d0f668d00 [0x108314a40]> {url = https://www.apple.com/, cs = 0x0}
      Error: Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7f8d0f590a80>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x7f8d0f50dfb0 [0x108314a40]>{type = immutable, count = 2, values = (
                0 : <cert(0x7f8d0f66ef10) s: www.apple.com i: Symantec Class 3 EV SSL CA - G3>
                1 : <cert(0x7f8d0f637e60) s: Symantec Class 3 EV SSL CA - G3 i: VeriSign Class 3 Public Primary Certification Authority - G5>
             )}}
    } [3:22]
Jan 31 17:09:13  test2[34612] <Notice>: CFNetwork Diagnostics [3:23] 17:09:13.125 {
               Did Fail
                 Loader: <CFURLRequest 0x7f8d0f737670 [0x108314a40]> {url = https://www.apple.com/, cs = 0x0}
                  Error: Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7f8d0f590a80>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x7f8d0f50dfb0 [0x108314a40]>{type = immutable, count = 2, values = (
                            0 : <cert(0x7f8d0f66ef10) s: www.apple.com i: Symantec Class 3 EV SSL CA - G3>
                            1 : <cert(0x7f8d0f637e60) s: Symantec Class 3 EV SSL CA - G3 i: VeriSign Class 3 Public Primary Certification Authority - G5>
                         )}}
    init to origin load: 0.00299901s
             total time: 0.156503s
            total bytes: 0
    } [3:23]

更新 2:

这是调试器中错误对象的视图。

【问题讨论】:

  • 我看到了同样的事情。

标签: ios ios-simulator ios9 app-transport-security nsapptransportsecurity


【解决方案1】:

NSRequiresCertificateTransparency 密钥是在 iOS 10 中引入的,所以我不确定为什么会失败。它绝对不会因为证书透明度而失败,因为 iOS9 不会检查它,但 iOS 10 会(因为 iOS 10 理解 NSRequiresCertificateTransparency 键)。

我确实确认这在运行 iOS 9 的物理设备上会失败。但并非所有服务器都失败。例如,www.google.com 可以在 iOS 9 的模拟器和物理设备上运行。

我建议打开 ATS 详细网络日志记录以确定 SSL 故障是由您的 ATS 配置引起的,还是其他原因引起的。请参阅有关如何打开详细日志记录 here 的详细信息。我怀疑还有另一个错误导致 SSL 错误。

另外,从 info.plist 中删除所有与 App Transport Security 相关的条目,看看它是否适用于 iOS 9。至少消除设置作为根本原因。

我能想到的唯一另一件事是,iOS9 对您有一个异常域而感到困惑,因为它下面没有有效的(就 iOS 9 而言)密钥,尽管我怀疑是这样。也许在您的 apple.com 异常域条目下添加一个值为 false 的 NSAllowsArbitraryLoads 键。

我建议在您不再需要支持 iOS 9 设备之前关闭该标志。

【讨论】:

  • 哦,我错过了它仅在 iOS 10 之后才可用。感谢您注意到这一点。然后确实很奇怪。正如我所说,如果我只是将其值从 YES 更改为 NO,则在 iOS 9 模拟器中连接成功。我也只是尝试更改参数的名称(将其保留为 YES),并且在这种情况下连接也成功。所以它似乎以某种方式“理解”标志 NSRequiresCertificateTransparency。添加 NSAllowsArbitraryLoads 也没有帮助。服务器是 www.apple.com。
  • 我已经尝试打开诊断日志记录。我在那里没有看到任何有用的东西。我用在那里看到的一些输出更新了我的问题。
  • 我确实验证了它在物理设备上失败。我相信这是一个错误。不确定可以用它做多少事情,因为 Apple 似乎对 iOS9 中的 NSRequiresCertificateTransparency 键进行了某种处理,但似乎没有正确实现。在您的应用程序不再支持 iOS9 之前,我会推迟将该密钥添加到您的 Info.plist 中。我也会将此问题报告给 Apple。
  • 另外值得注意的是,www.google.com 不会失败,即使在 iOS 9 中也是如此。这两个站点似乎支持证书透明度的方式不同,因此可能 iOS9 不支持 Apple 实现的证书透明度。 (ssllabs.com/ssltest/… 与 ssllabs.com/ssltest/…)
  • 我试过 www.google.com 也失败了。是不是忘记在Info.plist中更新域名了?
猜你喜欢
  • 2019-12-09
  • 2015-12-17
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
相关资源
最近更新 更多