CFNetwork SSLHandshake iOS 9失败

时间:2015-06-08 23:45:00

标签: ios ssl nsurlconnection ios9

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

我使用标准NSURLConnection连接到web服务,一旦调用webservice,我就会收到以下错误。这目前在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];

12 个答案:

答案 0 :(得分:309)

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,如果他们还没有这样做的话。这应该被视为一种临时解决方法。

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

答案 1 :(得分:64)

在iOS 10+中,TLS字符串必须是&#34; TLSv1.0&#34;的形式。它不能只是&#34; 1.0&#34;。 (叹气)

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

假设您正在尝试连接到只有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>

答案 2 :(得分:33)

了解更多信息Configuring App Transport Security Exceptions in iOS 9 and OSX 10.11

  

奇怪的是,您会注意到连接尝试更改   http协议以https来防止代码中的错误在哪里   您可能不小心错误配置了URL。在某些情况下,这   实际上可能有用,但它也令人困惑。

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

ATS失败

  

大多数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

答案 3 :(得分:2)

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

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

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

设置NSExceptionAllowsInsecureHTTPLoads = YES而非允许不安全连接,而不是允许降低安全性,以防服务器不符合最低要求(v1) .2)对于ATS(或更好地修复服务器端)。

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

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

App Transport Security(ATS)要求传输层安全性(TLS)协议版本1.2。

Requirements for Connecting Using ATS:

  

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

     

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

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

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

  •   
     

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

答案 4 :(得分:2)

经过两天的尝试和失败后,对我有用的是womble

的代码

有一个更改,根据此post,我们应该停止使用与此类约定的 NSExceptionDomains 字典相关联的子键

  NSTemporaryExceptionMinimumTLSVersion

并在新的公约中使用

  NSExceptionMinimumTLSVersion

代替。

apple documentation

我的代码

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

答案 5 :(得分:1)

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

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

提供输出

{{1}}

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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

答案 8 :(得分: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>

答案 9 :(得分:0)

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

  

iOS应用程序最终需要安全的HTTPS连接   2016.尝试关闭ATS可能会在未来拒绝您的应用。

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

然而,开发人员仍然可以关闭ATS并允许他们的应用程序通过HTTP连接发送数据,如上面的答案中所述。在2016年底,Apple将为所有希望将应用程序提交到App Store的开发人员强制 ATS 。链路

答案 10 :(得分:0)

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

答案 11 :(得分:-1)

info.plist如下或只是复制&amp;过去那项工作对我来说是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>