NSURLSession 的 IOS9 SSL 错误
Posted
技术标签:
【中文标题】NSURLSession 的 IOS9 SSL 错误【英文标题】:IOS9 SSL error with NSURLSession 【发布时间】:2015-07-19 20:51:33 【问题描述】:我开发了一个 ios 应用程序,它使用 HTTPs 与服务器通信(我也是服务器的开发人员,它嵌入了一个 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.
根据 Apple 文档,当错误 Code=-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);
我应该先创建自己的 CA,然后再创建自己的证书吗?如何进行?什么不见了?任何帮助将不胜感激。
塞巴斯蒂安。
【问题讨论】:
【参考方案1】:在与 Apple 支持讨论后,问题是由于自签名证书。
ATS 仅信任由知名 CA 签名的证书,所有其他证书均被拒绝。因此,使用自签名证书的唯一解决方案是使用 NSExceptionDomains 设置异常。
【讨论】:
这对你有用吗?我应该为我的域设置哪个例外?我已经尝试了几乎所有的组合,但仍然得到错误代码 -1200 ... Apple 声明我们应该添加“NSExceptionAllowsInsecureHTTPLoads”并将其设置为 true,以便可以访问域并出现错误。但我得到的只是一个没有响应的错误。 解决了我的问题,在我的情况下,我的测试域存在问题,没有证书但使用了 HTTPS 协议。为此,唯一的解决方案是在 Info.plist 中将 NSAllowsArbitraryLoads 异常设置为 true。【参考方案2】:不幸的是,您将需要从主要 CA 获得证书或设置一个只是临时修复的异常。你真的应该修复你的 SSL 并在SSL Labs 测试它
右键单击您的 Info.plist 并选择作为源代码打开。以下代码将允许您仅绕过您的服务器。文档是here
<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 编辑为属性列表来进行设置。看这篇文章WORKING WITH APPLE’S APP TRANSPORT SECURITY
【讨论】:
如果您没有域名,那么唯一的选择是使用 NSAllowsArbitraryLoads,例如:以上是关于NSURLSession 的 IOS9 SSL 错误的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 iOS 7 的 NSURLSession 接受自签名 SSL 证书