NSURLSession出现IOS9 SSL错误

seb*_*ien 9 authentication ssl x509certificate ios nsurlsession

我开发了一个使用HTTPs与服务器通信的IOS应用程序(我也是服务器的开发者,它嵌入了一个Tomcat服务器).

这个应用程序与IOS8没有任何问题,但它不适用于IOS9.

发送HTTPs请求时出现以下错误:

Session download has failed : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fa9c44b2e40 {NSErrorFailingURLStringKey=https://127.0.0.1:8443/MyServer/MyApp, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorFailingURLKey=https://127.0.0.1:8443/MyServer/MyApp, _kCFStreamErrorCodeKey=-9802, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}
Run Code Online (Sandbox Code Playgroud)

根据Apple文档,当错误代码= -1200发生时,这是因为TLSv1.1而不是TLSv1.2.我已经使用openSSL命令验证了我的服务器正在使用TLSv1.2.

在info.plist中设置属性NSAllowsArbitraryLoads = true时,错误消失但我不想保持这样.

我的服务器使用自签名证书,可能是问题的原因?下面是我用于didReceiveChallenge的代码

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {

[RequestURLUtilities dumpChallenge:challenge];


if (challenge.protectionSpace != Nil) {
    NSURLProtectionSpace *protection = challenge.protectionSpace;

    SecTrustRef sslState = protection.serverTrust;
    if (sslState == Nil) {
        NSLog(@"%s Warning: empty serverTrust",__PRETTY_FUNCTION__);
    }


    if ([protection.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

        NSLog(@"%s => NSURLAuthenticationMethodServerTrust", __PRETTY_FUNCTION__);
        // warning normaly I should check the validity of the SecTrustRef before to trust
        NSURLCredential* credential = [NSURLCredential credentialForTrust:sslState];

        // Put in command for test

       completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

    } else {
        NSLog(@"%s => Called for another challenge", __PRETTY_FUNCTION__);
       completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);
    }

}
Run Code Online (Sandbox Code Playgroud)

我应该创建自己的CA,然后创建自己的证书吗?如何进行?缺什么?任何帮助将不胜感激.

塞巴斯蒂安.

seb*_*ien 11

在与Apple支持人员进行一些讨论后,问题是由于自签名证书.

ATS仅信任由知名CA签署的证书,所有其他证书都被拒绝.因此,具有自签名证书的唯一解决方案是使用NSExceptionDomains设置异常.


Rob*_*tal 5

不幸的是,您需要从主要CA获取证书或设置仅作为临时修复的异常.您真的应该修复您的SSL并在SSL实验室进行测试

右键单击Info.plist并选择open作为源代码.以下代码将允许您仅绕过您的服务器.文档在这里

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
  </dict>
</dict>
Run Code Online (Sandbox Code Playgroud)

您也可以通过将info.plist编辑为属性列表来设置此项.请参阅此文章使用APPLE的APP运输安全