与NSURLSession的IOS9 SSL错误

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

这个应用程序没有任何IOS8的问题,但它不与IOS9。

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

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

基于苹果的文档,当错误Code = -1200发生时,这是因为TLSv1.1而不是TLSv1.2。 我已经用openSSL命令进行了validation,我的服务器正在使用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); } } 

我应该创build自己的CA,然后创build自己的证书吗? 如何进行? 什么不见​​了? 任何帮助将不胜感激。

塞巴斯蒂安。

在与Apple支持部门进行了一些讨论之后,问题归因于自签名证书。

ATS仅信任由知名CA签署的证书,其他人均被拒绝。 因此,具有自签名证书的唯一解决scheme是使用NSExceptionDomains设置一个exception。

不幸的是,你需要从一个主要的CA获得一个证书,或者设置一个只有临时修复的exception。 您确实应该修复您的SSL,并在SSL实验室进行testing

右键单击您的Info.plist并select作为源代码打开。 以下代码将允许您绕过您的服务器而已。 文档在这里

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

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