CFNetwork SSLHandshake失败的iOS 9

有任何人与iOS 9测试版1有这个问题?

我使用标准的NSURLConnection来连接到一个web服务,一旦打电话给web服务,我得到下面的错误。 这是目前在iOS 8.3中工作

可能的beta bug? 任何想法或想法将是伟大的! 我知道它在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]; 

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

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测试版:**

在iOS 10中,TLS字符串必须是“TLSv1.0”的格式。 它不能只是“1.0”。 是的,这是非常愚蠢和破坏性的。 欢迎来到iOS开发。


以上建议的组合如下。

假设您正尝试连接到只有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中配置App Transport安全例外

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

使用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 

如果你的后端使用安全的连接蚂蚁你使用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进行连接的要求:

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

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

  • 安全散列算法2(SHA-2)密钥的摘要长度至少为256(即SHA-256或更高)
  • 椭圆曲线加密(ECC)密钥,大小至少为256位

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

以下连接密码支持前向保密(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 链接

经过两天的尝试和失败,对我来说有效的是这个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> 

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

这个错误有时出现在日志中,当我使用一个错误/崩溃的科尔多瓦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> 

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

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

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

但是,开发人员仍然可以切换ATS,并允许他们的应用程序通过HTTP连接发送数据,如上面的答案中所述。 在2016年年底,苹果将使所有希望将应用程序提交到App Store的开发者强制使用ATS 。 链接

为什么使它太复杂 –

只需设置iOS开发目标 – 8.0

在这里输入图像描述

在这里输入图像描述

Cmd + Shift + K

我测试的设备时间设置错误。 所以,当我尝试访问一个证书,即将用尽的页面,将拒绝访问,因为设备虽然证书已过期。 要修复,请在设备上设置适当的时间!

info.plist如下或只是复制和过去的工作对我来说,到iOS 9.2

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>$(PRODUCT_NAME)</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.0</string> <key>LSRequiresIPhoneOS</key> <true/> <key>UILaunchStoryboardName</key> <string>LaunchScreen</string> <key>UIMainStoryboardFile</key> <string>Main</string> <key>UIRequiredDeviceCapabilities</key> <array> <string>armv7</string> </array> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> </dict> </plist>