iOS 9.3:发生SSL错误,无法与服务器建立安全连接

时间:2016-03-31 11:05:38

标签: ios swift ssl-certificate alamofire nsurlsession

我收到自签名证书的错误

  

错误域= NSURLErrorDomain代码= -1200"发生了SSL错误   并且无法与服务器建立安全连接。

在使用

测试我的某个演示应用的网络服务时

注意: 在假设其重复之前,我会请求请一直阅读,即使我已向苹果开发论坛报告

使用 Alamofire图书馆

func testAlamofireGETRequest() -> Void
    {
        Alamofire.request(.GET, "https://filename.hostname.net/HelloWeb/service/greeting/john")
            .responseJSON
        { response in
            print("Response JSON: \(response.result.value)")
        }
}

使用 NSURLSession

func testNSURLSessionRequest() -> Void {

        let session = NSURLSession.sharedSession()
        let urlString = "https://filename.hostname.net/HelloWeb/service/greeting/john"
        let url = NSURL(string: urlString)
        let request = NSURLRequest(URL: url!)
        let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
            print("done, error: \(error)")

            //Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
        }
        dataTask.resume()
    }
  

我花了2天没有运气:(

     

已经发布了一堆问题,但没有对我有用

发布了Alamofire git issue

我的 Info.pist 文件以这种方式更新了ATS设置

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>filename.hostname.net</key>
            <dict>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>

同时我能够得到回应

HTTP ://filename.hostname.net

https ://google.com

不适用于 https ://filename.hostname.net

任何人都可以建议我为什么在经过巨大努力后无法让这项工作得以实现?

4 个答案:

答案 0 :(得分:40)

在OS X的命令行中,运行以下命令:

nscurl --ats-diagnostics https://filename.hostname.net --verbose

这将告诉您什么样的ATS设置组合将允许iOS访问您的网站,并指出您的网站有什么问题。

可能是以下一个或多个

  • 证书哈希算法(必须是SHA-256或以上)
  • TLS版本(必须为1.2)
  • TLS算法(必须提供Perfect Forward Secrecy)

答案 1 :(得分:8)

Apple已发布App Transport Security的完整要求列表。

原来我们正在使用TLS v1.2但是缺少其他一些要求。

Here's the full check list

  • TLS至少需要1.2版本。
  • 连接密码仅限于提供前向保密的密码(请参阅下面的密码列表。)
  • 该服务需要至少使用带有2048位或更高RSA密钥的SHA256指纹或256位或更高椭圆曲线(ECC)密钥的证书。
  • 无效的证书会导致硬故障并且无法连接。
  • 接受的密码是: 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

答案 2 :(得分:4)

我认为您尝试连接的服务器具有无效证书,或者与ECC,密码等的iOS 9标准不匹配。

  • 如果您正在使用高级网络API-NSURLSession,NSURLConnection或其他任何分层 - 您无法直接控制客户端提供的密码套件。这些API使用自己的内部逻辑选择一组cypher套件。

  • 如果您正在使用较低级别的网络API-CFSocketStream,通过其NSStream和CFStream API以及任何低于此值的任何内容,您可以明确选择要使用的cypher套件集。如何执行此操作取决于具体的API。

标准做法是:

  1. 创建流对

  2. 为TLS配置

  3. 使用kCFStreamPropertySSLContext属性获取安全传输上下文

  4. 在该上下文中配置特定属性

  5. 打开溪流

  6. 您可以在TLSTool示例代码中看到此示例。具体来说,请查看TLSToolServer类,您可以在其中查看此序列。

    在非常短的环境中,您希望以绕过安全性的方式配置流,但是,在Alamofire的情况下,您可以通过以下方式直接执行此操作:

    func bypassAuthentication() {
            let manager = Alamofire.Manager.sharedInstance
            manager.delegate.sessionDidReceiveChallenge = { session, challenge in
                var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
                var credential: NSURLCredential?
                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                    disposition = NSURLSessionAuthChallengeDisposition.UseCredential
                    credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
                } else {
                    if challenge.previousFailureCount > 0 {
                        disposition = .CancelAuthenticationChallenge
                    } else {
                        credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
                        if credential != nil {
                            disposition = .UseCredential
                        }
                    }
                }
                return (disposition, credential)
            }
        }
    

    如果有帮助,请告诉我。 谢谢!

答案 3 :(得分:3)

我有同样的情景,并且被困了一天。尝试使用您的移动数据,如果这适用于您的API,那么您的网络防火墙就会出现问题。然后从防火墙设置启用SSL / TLS。