CFNetwork SSLHandshake iOS 9失败

有人用过iOS 9 beta 1吗?

我使用标准的NSURLConnection连接到一个webservice,一旦调用到webservice,我就会得到下面的错误。目前在iOS 8.3中运行

可能是测试版bug?任何想法都很好!我知道这是在iOS 9开发的早期

以下是完整的错误:

CFNetwork SSLHandshake failed (-9824) NSURLSession/NSURLConnection HTTP load failed (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];
120523 次浏览

iOS 9和OSX 10.11要求所有你计划请求数据的主机使用TLSv1.2 SSL,除非你在应用程序的信息中指定了例外域。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,如果它们还没有这样做的话。这应该被认为是一个临时的解决办法。

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

在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>

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

奇怪的是,您将注意到连接试图更改 HTTP协议转换为HTTPS,以防止在代码中出现错误 你可能不小心配置错了URL。在某些情况下,这

这个使用应用程序传输安全性发布应用程序包含了一些很好的调试技巧

美国胸科协会失败

大多数ATS失败将显示为CFErrors,代码为-9800 系列。这些在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

如果你的后端使用安全连接,你可以使用NSURLSession

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

您需要检查您的服务器配置,特别是获得ATS版本和SSL证书

通过设置NSExceptionAllowsInsecureHTTPLoads = YES,而不仅仅是允许不安全连接,相反,你需要允许降低安全性,以防你的服务器不满足ATS的最小要求(v1.2)(或者更好地修复服务器端)。

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

<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连接要求: . sh ATS连接要求

使用应用程序传输安全(ATS)的web服务连接要求包括服务器、连接密码和证书,如下所示:

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

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

  • 至少256位的ECC密钥

  • RSA密钥,长度至少为2048位

    .证书无效导致硬失效,无法连接

以下连接密码支持前向保密(FS)和工作 ATS: < / p > < p > 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 < / p >

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

当我使用一个有bug /崩溃的Cordova iOS版本时,这个错误有时会出现在日志中。当我升级或降级cordova iOS时,它就消失了。

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

在你的项目.plist文件中添加这个权限:

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

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年全球开发者大会后):

iOS应用程序将要求安全HTTPS连接结束 2016.

.关闭ATS可能会导致你的应用在将来被拒绝

应用程序传输安全(ATS)是苹果在iOS 9中引入的一项功能。当ATS被启用时,它会强制应用程序通过HTTPS连接而不是不安全的HTTP连接到web服务。

但是,开发人员仍然可以关闭ATS,并允许他们的应用程序通过HTTP连接发送数据,就像上面的回答中提到的那样。在2016年底,苹果将为所有希望向App Store提交应用程序的开发者提供美国胸科协会强制。链接

另一个有用的工具是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

经过两天的尝试和失败,对我有用的是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>

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