NSURLSession "HTTP 加载失败 kCFStreamErrorDomainSSL, -9813 ; 自签名证书

Posted

技术标签:

【中文标题】NSURLSession "HTTP 加载失败 kCFStreamErrorDomainSSL, -9813 ; 自签名证书【英文标题】:NSURLSession "HTTP load failed kCFStreamErrorDomainSSL, -9813 ; Self signing certificate 【发布时间】:2015-08-27 18:32:29 【问题描述】:

我正在尝试将我的 ios 应用程序连接到当前在我网络中的本地主机上运行的 HTTPS Rails 应用程序。我可以使用 https://myIP:3000/display 从浏览器访问该站点,也可以使用 curl 请求在命令行中访问该站点。我正在尝试使用以下方式从我的应用程序中访问它:

class FirstViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        //let url = NSURL(string: "https://another/Sinatra/website/feed")
        let url = NSURL(string: "https://myIP:3000/display")

        let request = NSURLRequest(URL: url!)
        let task = NSURLSession.sharedSession().dataTaskWithURL(url!)
        task!.resume()
    

当我尝试访问 sinatra 网站时,我没有遇到任何问题,甚至可以使用正确的命令将 JSON 打印到控制台。但是,当我将 url 设置为我的 Rails 网站时,我收到以下错误。

NSURLSession/NSURLConnection HTTP 加载失败 (kCFStreamErrorDomainSSL, -9813)

此外,我可以看出我的 localhost Rails 应用程序(在另一台机器上)没有从 iOS 应用程序 ping,而是从浏览器和 curl 命令 ping。

任何想法如何解决这个问题?

【问题讨论】:

将您的代码放入viewWillDisplayviewDidDisplayviewDidLoad 对大多数事情来说都太早了。 iOS 和 Swift 哪个版本?将该信息添加到问题中。 CFNetwork SSLHandshake failed iOS 9 Beta 1 的可能重复项 NSURLSession/NSURLConnection HTTP load failed的可能重复 也发生在 Objective C 中(不仅在 swift 上) 【参考方案1】:

如果我理解得很好,Apple 现在希望开发人员使用 HTTPS 和 TLS 1.2 进行网络调用。

临时的,你可以在你的“Info.plist”文件中添加这个:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

看看这个链接,它也可能对你有帮助:http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

--

更新:在一些 cmets 之后,上述解决方案不再有效。这是一个更新的解决方案。

    转到您的 Info.plist 文件。 添加一行 Type DictionaryKey App Transport Security Settings。 在此字典中,添加一行 Type BooleanKey Allow Arbitrary LoadsValue YES

-

否则你可以设置Domain Exceptions。这是怎么做的:

    转到您的 Info.plist 文件。 添加一行 Type DictionaryKey App Transport Security Settings。 添加一行 Type DictionaryKey Exception Domains。 添加一行 Type DictionaryKey The domain。 将两行 Type BooleanKey NSExceptionAllowsInsecureHTTPLoads & NSIncludesSubdomainsValue 添加到 YES

链接

https://forums.developer.apple.com/message/5857#5857

2015 WWDC Session 711

iOS 9 HTTP Connection Error - ***

【讨论】:

不只是 https,它必须是 TLS 1.2。 这在 iOS 模拟器中似乎不起作用。你在模拟器中工作了吗? 不再适用于 iOS 10。修复方法是什么? (感谢 Apple 让我们知道他们会破坏我们的应用程序 - 不是 :-) 有趣的是,我在使用 TLS 1.2 连接时遇到了类似的错误。这是与具有真实 SSL 证书的生产服务器通信。 Allow Arbitrary Loads 使这项工作。【参考方案2】:

这是一个信任问题。使用自签名证书,SSL 的身份验证组件不起作用。仍然可以建立安全连接,以便没有人窃听,但应用程序无法确定谁在线路的另一端。

我有类似的设置,并通过将我的自签名根 CA 添加到 iPad 受信任证书来解决此问题。这个根 CA 用于签署我所有的其他开发证书。然后我只需在将使用 SSL 的任何地方添加这个单一的根证书。如果您只有一个直接使用的自签名证书,您可以添加它。

为了在设备(或模拟器)上获取证书,我将文件放在我的网络服务器上。然后只需通过普通 HTTP 在 Safari 中打开它。设置应用程序应该会打开并询问您是否要信任证书。

当然,这是假设这仅用于开发,并且您的生产系统具有由知名机构签署的证书(即包含在操作系统的根证书机构数据库中的证书)。因为要求最终用户安装您的自签名证书是行不通的。

【讨论】:

是的,但是您将哪个文件放在服务器上?我把我的 .cert 和 Safari 只是作为文本文件打开。 我将我的自签名根 CA 放在服务器上并在 Safari 中打开它。我使用了扩展名.crt 我的服务器正在使用 真实 证书(非自签名),但我仍然遇到此问题...【参考方案3】:

这是唯一对我有用的解决方案...在 AppDelegate.m 文件的末尾,插入代码:

@implementation NSURLRequest(DataController)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host

return YES;

@end

感谢 jc ivancevich 的文章http://ivancevich.me/articles/ignoring-invalid-ssl-certificates-on-cordova-android-ios/

【讨论】:

【参考方案4】:

(编辑 - 我将其误读为 9814,证书已过期。我不确定如何解决这个问题,但希望我的回答有助于指明正确的方向。)

看起来像是与通常的“允许任意负载”问题不同的证书问题。

摘自:Apple Documentation - Appendix A: Common Server Trust Evaluation Errors

NSOSStatusErrorDomain errSSLNoRootCert -9813

【讨论】:

【参考方案5】:

尝试改变会话变量,这个改变对我有帮助

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)

【讨论】:

【参考方案6】:

修改 info.plist 也对我有用。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

【讨论】:

【参考方案7】:

NSURLSession/NSURLConnection HTTP 加载失败 (kCFStreamErrorDomainSSL, -9813)

在您的 plist 文件中添加一个新行。

【讨论】:

这只是对现有答案的重复。

以上是关于NSURLSession "HTTP 加载失败 kCFStreamErrorDomainSSL, -9813 ; 自签名证书的主要内容,如果未能解决你的问题,请参考以下文章

使用NSURLSession同步获取数据(通过添加信号量)

使用 NSURLSession 处理 HTTP 错误的最佳实践?

带有 NSURLSession 的 Swift 中的 HTTP 请求

NSURLSession HTTP/2 内存泄漏

iOS10 NSURLSession HTTP/2 无效

带有 NSURLSession 的 Http/2 server_push