207

有 iOS 9 beta 1 的人有这个问题吗?

我使用标准 NSURLConnection 连接到网络服务,一旦调用网络服务,我就会收到以下错误。这目前在 iOS 8.3 中工作

可能的测试错误?任何想法或想法都会很棒!我知道它在 iOS 9 开发的早期

这是完整的错误:

CFNetwork SSLHandshake 失败 (-9824) NSURLSession/NSURLConnection HTTP 加载失败 (kCFStreamErrorDomainSSL, -9824)

 NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://mywebserviceurl"]];
        NSURLResponse * response = nil;
        NSError * error = nil;
        NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                                  returningResponse:&response
                                                              error:&error];
4

11 回答 11

310

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>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

如果您的应用程序(例如第三方 Web 浏览器)需要连接到任意主机,您可以像这样配置它:

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

如果您必须这样做,最好更新您的服务器以使用 TLSv1.2 和 SSL,如果他们还没有这样做的话。这应该被认为是一种临时的解决方法。

截至今天,预发布文档没有以任何特定方式提及任何这些配置选项。完成后,我将更新答案以链接到相关文档。

于 2015-06-08T23:58:56.327 回答
66

在 iOS 10+ 中,TLS 字符串的格式必须为“TLSv1.0”。它不能只是“1.0”。(叹)


以下其他答案的组合有效。

假设您正在尝试连接到只有 TLS 1.0 的主机 (YOUR_HOST.COM)。

将这些添加到您应用的 Info.plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_HOST.COM</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>
于 2015-06-17T03:52:34.733 回答
33

有关更多信息在 iOS 9 和 OSX 10.11 中配置应用程序传输安全例外

奇怪的是,您会注意到连接尝试将 http 协议更改为 https 以防止代码中出现您可能不小心错误配置 URL 的错误。在某些情况下,这可能确实有效,但也令人困惑。

This Shipping an App With App Transport Security涵盖了一些很好的调试技巧

ATS 故障

大多数 ATS 故障将显示为带有 -9800 系列代码的 CFErrors。这些在 Security/SecureTransport.h 头文件中定义

2015-08-23 06:34:42.700 SelfSignedServerATSTest[3792:683731] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

CFNETWORK_DIAGNOSTICS

将环境变量 CFNETWORK_DIAGNOSTICS 设置为 1,以便在控制台上获取有关故障的更多信息

nscurl

该工具将运行多种不同的 ATS 异常组合,尝试在每个 ATS 配置下与给定主机建立安全连接并报告结果。

nscurl --ats-diagnostics https://example.com
于 2015-08-17T08:41:00.097 回答
2

如果您的后端使用安全连接蚂蚁,您可以使用 NSURLSession

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

您需要检查您的服务器配置,尤其是获取 ATS 版本和 SSL 证书信息:

如果您的服务器不满足 ATS 的最低要求 (v1.2)(或更好地修复服务器端) ,您不仅需要通过设置允许不安全连接NSExceptionAllowsInsecureHTTPLoads = YES,还需要允许降低安全性。

允许降低单个服务器的安全性

<key>NSExceptionDomains</key>
<dict>
    <key>api.yourDomaine.com</key>
    <dict>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>TLSv1.0</string>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <false/>
    </dict>
</dict>

使用 openssl 客户端调查证书并使用 openssl 客户端获取您的服务器配置:

openssl s_client  -connect api.yourDomaine.com:port //(you may need to specify port or  to try with https://... or www.)

..在最后找到

SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: //
    Session-ID-ctx: 
    Master-Key: //
    Key-Arg   : None
    Start Time: 1449693038
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

应用传输安全 (ATS) 需要传输层安全 (TLS) 协议版本 1.2。

使用 ATS 连接的要求:

使用 App Transport Security (ATS) 的 Web 服务连接要求涉及服务器、连接密码和证书,如下所示:

证书必须使用以下类型的密钥之一进行签名:

  • 安全散列算法 2 (SHA-2) 密钥,摘要长度至少为 256(即 SHA-256 或更大)

  • 椭圆曲线加密 (ECC) 密钥,大小至少为 256 位

  • 长度至少为 2048 位的 Rivest-Shamir-Adleman (RSA) 密钥 无效证书会导致硬故障且无连接。

以下连接密码支持前向保密 (FS) 并与 ATS 一起使用:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

更新:原来 openssl 只提供最小协议版本协议:TLSv1 链接

于 2015-12-09T21:40:29.220 回答
2

经过两天的尝试和失败,对我有用的是这个womble代码

有一个变化,根据这篇文章,我们应该停止使用与那种约定的NSExceptionDomains字典相关联的子键

  NSTemporaryExceptionMinimumTLSVersion

并在新公约中使用

  NSExceptionMinimumTLSVersion

反而。

苹果文档

我的代码

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>YOUR_HOST.COM</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
于 2016-12-06T11:52:29.390 回答
1

另一个有用的工具是 nmap(brew install nmap)

nmap --script ssl-enum-ciphers -p 443 google.com

给出输出

Starting Nmap 7.12 ( https://nmap.org ) at 2016-08-11 17:25 IDT
Nmap scan report for google.com (172.217.23.46)
Host is up (0.061s latency).
Other addresses for google.com (not scanned): 2a00:1450:4009:80a::200e
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: client
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 5.48 seconds
于 2016-08-11T14:28:11.483 回答
0

当我使用有缺陷/崩溃的 Cordova iOS 版本时,有时会在日志中显示此错误。当我升级或降级科尔多瓦 iOS 时,它就消失了。

我连接的服务器使用的是 TLSv1.2 SSL,所以我知道这不是问题所在。

于 2016-03-11T19:20:02.677 回答
0

在您的项目 .plist文件中添加此权限:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
于 2016-03-30T10:59:30.247 回答
0

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>NSExceptionAllowsInsecureHTTPLoads</key>
  <true/>
  <!--Include to specify minimum TLS version-->
  <key>NSExceptionMinimumTLSVersion</key>
  <string>TLSv1.1</string>
   </dict>
 </dict>

于 2016-06-03T10:47:20.220 回答
0

更新的答案(WWDC 2016 之后):

到 2016 年底,iOS 应用程序将需要安全的 HTTPS 连接。尝试关闭 ATS 可能会导致您的应用程序在未来被拒绝。

App Transport Security 或 ATS 是 Apple 在 iOS 9 中引入的一项功能。启用 ATS 后,它会强制应用程序通过 HTTPS 连接而不是不安全的 HTTP 连接到 Web 服务。

但是,开发人员仍然可以关闭 ATS 并允许他们的应用程序通过 HTTP 连接发送数据,如上述答案中所述。2016 年底,Apple 将对所有希望将其应用程序提交到 App Store 的开发者强制执行 ATS 。关联

于 2016-06-15T10:39:21.170 回答
0

我测试的设备设置了错误的时间。因此,当我尝试使用即将用完的证书访问页面时,它会拒绝访问,因为设备虽然证书已过期。要修复,请在设备上设置适当的时间!

于 2017-01-04T11:51:55.650 回答