NSURLSession/NSURLConnection 在 iOS 9 上的 HTTP 加载失败

137

尝试在iOS9上运行现有应用程序,但在使用AFURLSessionManager时失败。

__block NSURLSessionDataTask *task = [self.sessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
    if (error) {

    } else {

    }
}];

[task resume];

我遇到了以下错误:

Error Domain=NSURLErrorDomain Code=-999 "cancelled.

同时还收到以下日志:

 NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824
 CFNetwork SSLHandshake failed (-9824)

更新: 我已经对我的解决方案进行了多次更新: NSURLSession/NSURLConnection在iOS 9上发生HTTP加载失败


你确定错误是发生在第一行吗? - BSMP
1
我也遇到了同样的问题。这个链接似乎解决了这个问题:https://dev59.com/Tl0a5IYBdhLWcg3wF1UL - phillies2628
13个回答

240

找到解决方案:

iOS9中,ATS在网络调用期间强制执行最佳实践,包括使用HTTPS。

来自苹果文档:

ATS可以防止意外泄露信息,提供安全的默认行为,并且易于采用。不论是创建新应用程序还是更新现有应用程序,您都应该尽快采用ATS。 如果您正在开发新应用程序,则应仅使用HTTPS。如果您有现有应用程序,则应立即尽可能多地使用HTTPS,并制定迁移应用程序其余部分的计划。

在测试版1中,目前无法在info.plist中定义此内容。 解决方案是手动添加:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

图片描述

更新1:这是一个临时解决方法,直到您准备采用iOS9 ATS支持。

更新2:有关更多详细信息,请参阅以下链接: http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

更新3:如果您正试图连接只支持TLS 1.0的主机(YOURHOST.COM)

请将以下内容添加到您应用程序的Info.plist中:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOURHOST.COM</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

10
请注意,您刚刚完全禁用了应用程序传输安全功能,因此您的应用程序中就丢失了一个重要的iOS 9功能。这是一种黑客行为,如果使用此方法可能会导致您的应用被拒绝。将特定网站添加到字典中更有可能被允许。 - gnasher729
2
@StevenPeterson 你只能通过逐个申请的方式让苹果公司将整个应用程序排除在外。我认为如果苹果公司允许你的应用程序具备这种能力,他们会指示你包含此密钥。预计苹果公司很少这样做。 - mattyohe
8
请不要仅仅将例外情况添加到您的属性列表(plist)中并且忽略它,只因为这个方法可行。请考虑您用户数据的安全,并且实施 SSL 和其他安全最佳实践。 - Andrew
8
@gnasher729,我知道支持TLS 1.2比仅禁用ATS更好。但是,如果您依赖于第三方API / Web服务,该怎么办?我无法强制升级它们,那我该怎么做? - Woodstock
7
这个答案中存在一个微妙的错误:NSTemporaryExceptionMinimumTLSVersion 必须为例如 TLSv1.0 而不是 _1.0_,请参见NSAppTransportSecurity Exception domains dictionary keys - mbi
显示剩余6条评论

54

如何处理iOS9中的SSL问题?一种解决方案是像这样做:

正如苹果所说: enter image description here enter image description here

enter image description here

iOS 9和OSX 10.11要求所有您计划从中请求数据的主机使用TLSv1.2 SSL,除非您在应用程序的Info.plist文件中指定了例外域名。

Info.plist配置的语法如下:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow insecure HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

如果您的应用程序(例如第三方网络浏览器)需要连接到任意主机,您可以进行如下配置:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

如果您不得不这样做,最好更新服务器以使用TLSv1.2和SSL,如果它们还没有这样做。这应该被视为一个临时解决方案。

截至今天,预发行文档没有以任何特定方式提到这些配置选项。一旦有了相关的文档,我会更新答案并链接到相关文档。

欲了解更多信息,请访问iOS9AdaptationTips


4
SSL和TLS是HTTPS协议使用的不同加密层。因此,应该完全禁用SSL并使用TLS v1.2或更高版本。如需了解更多信息,请参考以下资源:SSL / TLS Security 2015-简化快速指南 - Conrad Taylor
2
我只在将NSAllowsArbitraryLoads设置为true的底部示例中运气不佳。我的服务器仅使用TLS v1.2,但我仍然必须这样做才能使其正常工作。非常令人沮丧。 - Scooter
1
那么,有没有什么变通方法可以使用,以确保我的新应用程序能够在应用商店获得批准,例如代理服务? - Josh

41
苹果公司有关应用程序传输安全的技术说明非常有用,它帮助我们找到了一个更安全的解决方案来解决我们的问题。
希望这对别人也有所帮助。我们曾经遇到连接 Amazon S3 URL 的问题,看起来这些 URL 是完全有效的 TLSv12 HTTPS URL。后来发现我们必须禁用 "NSExceptionRequiresForwardSecrecy" 才能启用 S3 使用的其他一些密码。
在我们的 "Info.plist" 中:
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>amazonaws.com</key>
    <dict>
      <key>NSIncludesSubdomains</key>
      <true/>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
  </dict>
</dict>

这正是我的问题,它立即解决了!谢谢! :) - Alex Zak
这也解决了我遇到的问题;不过不同情况可能需要不同的设置。好消息是,该技术说明还包含有关如何使用NSURL来帮助您通常找到正确设置的信息。 - ecotax
如果我在Amazon S3前面使用CDN,我需要对cloudfront.net做同样的操作。 - Raymond26

7
如果您遇到了Amazon S3的问题,可以尝试将以下内容粘贴到您的info.plist文件中,作为最高级别标签的直接子项。
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>amazonaws.com</key>
        <dict>
              <key>NSThirdPartyExceptionMinimumTLSVersion</key>
              <string>TLSv1.0</string>
              <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
              <false/>
              <key>NSIncludesSubdomains</key>
              <true/>
        </dict>
        <key>amazonaws.com.cn</key>
        <dict>
              <key>NSThirdPartyExceptionMinimumTLSVersion</key>
              <string>TLSv1.0</string>
              <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
              <false/>
              <key>NSIncludesSubdomains</key>
              <true/>
        </dict>
    </dict>
</dict>

您可以在以下网址找到更多信息:

http://docs.aws.amazon.com/mobile/sdkforios/developerguide/ats.html#resolving-the-issue


2
God bless you bro - Vervatovskis

5

我从这里找到了解决方案,对我很有效。

你可以看一下,也许对你有帮助。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
         <dict>
             <key>myDomain.com</key>
                    <dict>
                      <!--Include to allow subdomains-->
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <!--Include to allow HTTP requests-->
                      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                      <true/>
                      <!--Include to specify minimum TLS version-->
                      <key>NSTemporaryExceptionMinimumTLSVersion</key>
                      <string>TLSv1.1</string>
                </dict>
          </dict>
</dict>

4

只需在您的 .plist 文件中添加以下字段

enter image description here

语法如下:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

这将允许所有的HTTP请求。虽然可行,但不建议使用。 - KVISH

2

更新:

自Xcode 7.1起,您无需手动输入NSAppTransportSecurity字典到info.plist中。

现在它将自动完成,实现它是一个字典,然后自动完成Allows Arbitrary Loads。

info.plist截图

这将允许所有的HTTP请求。虽然可以运行,但不建议使用。 - KVISH

2
解决 NSURLConnection Http 加载失败问题,只需在 info.plist 文件中添加以下字典即可:
<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
        <true/>
    </dict>

1
这是我在遇到这个错误时所做的事情:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
        </dict>
    </dict>
</dict>

1
您可以尝试将此函数添加到文件 RCTHTTPRequestHandler.m 中:
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接