iOS 8 在我的应用程序中断开了 SSL 连接 - CFNetwork SSLHandshake failed (-9806)

Posted

技术标签:

【中文标题】iOS 8 在我的应用程序中断开了 SSL 连接 - CFNetwork SSLHandshake failed (-9806)【英文标题】:iOS 8 has broken SSL connection in my app - CFNetwork SSLHandshake failed (-9806) 【发布时间】:2014-11-12 21:17:53 【问题描述】:

我的应用只是连接到家用设备上的网络服务器并读取一些 html。 使用 http 时它可以正常工作,但现在在 ios 8 上使用 https 时它不起作用。

我使用AFNetworking v1 并使用这些覆盖方法覆盖 SSL 检查(是的,我知道在正常情况下不应该这样做,而且不安全等等,但那是另一个话题)。

[self setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) 
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) 
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        
    ];

[self setAuthenticationAgainstProtectionSpaceBlock:^BOOL(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace) 
        if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) 
                return YES; // Self-signed cert will be accepted
        
        // If no other authentication is required, return NO for everything else
        // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
        return NO;
    ];

现在在 iOS 8 中出现如下错误:

CFNetwork SSLHandshake 失败 (-9806)

CFNetwork SSLHandshake 失败 (-9806)

CFNetwork SSLHandshake 失败 (-9806)

NSURLConnection/CFURLConnection HTTP 加载失败 (kCFStreamErrorDomainSSL, -9806)

连接期间出错:Error Domain=NSURLErrorDomain Code=-1200 “发生 SSL 错误,无法与服务器建立安全连接。” UserInfo=0x7b66c110 NSLocalizedDescription=发生 SSL 错误,无法建立与服务器的安全连接。, NSLocalizedRecoverySuggestion=您是否仍要连接到服务器?, _kCFStreamErrorCodeKey=-9806, NSErrorFailingURLStringKey=https://xxx.xxx.xxx.xxx:443/live.htm, _kCFStreamErrorDomainKey=3 , NSUnderlyingError=0x7c0d8a20 "发生 SSL 错误,无法与服务器建立安全连接。", NSErrorFailingURLKey=https://xxx.xxx.xxx.xxx:443/Info.live.htm

我已经尝试切换到 FSNetworking,并且 sometimes 在设置时有效:

- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    
        NSLog(@"Ignoring SSL");
        SecTrustRef trust = challenge.protectionSpace.serverTrust;
        NSURLCredential *cred;
        cred = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
        return;
    

但是同时进行 2 个请求,只有 1 个会成功,一个会失败,并出现与上述类似的错误。似乎只有 1 个请求到达 SSL 覆盖点。

谁能解释一下这个问题以及 iOS 8 中发生了什么改变来打破这个问题,以及我该如何解决它?

谢谢

【问题讨论】:

以下是包含您的错误代码的列表:opensource.apple.com/source/libsecurity_ssl/… 【参考方案1】:

我在使用 iOS 8 时遇到了同样的问题。

场景:

    调用我们的 https 服务器工作 在UIWebView 中从我们的服务器打开一个 https URL 所有未来的NSURLConnections 都失败并出现SSLHandshake 错误

当我们立即调用 SecTrust* 方法时,useCredential:forAuthenticationChallenge 导致了此错误(但仅在打开同一服务器上托管的 https 页面后)。

此代码触发了错误:

[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);

但是这个没有:

SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];

我不清楚为什么这会导致 SSLHandshake 在 iOS 8 而不是 iOS 7 上失败。也许 AFNetworking 在 useCredential:forAuthenticationChallenge 之后做了一些事情,这导致了同样的问题。

【讨论】:

谢谢。这与我上面的基本相同。我认为我问题底部的代码实际上是有效的,它有时不起作用的原因与这个github.com/AFNetworking/AFNetworking/issues/…【参考方案2】:

您看到的错误可以在SecureTransport.h 中找到。这是一个传输级错误:连接失败,因为它被中止了。

在客户端和服务器上都有很多原因。如果服务器向客户端请求证书而客户端没有提供证书,则更可能发生这种情况,此时服务器决定放弃。如果服务器要求客户端提供证书,您的委托方法应该会看到除了服务器信任之外还尝试使用客户端证书进行身份验证。

【讨论】:

谢谢。我不太清楚从 iOS 7 到 8 发生了什么变化使其突然停止工作。我已经更新到 AFNetworking v2 并获得身份验证质询回调,基本上告诉它忽略并继续。这似乎有时有效,但并非总是如此。我想知道是否需要将所有请求排队,以便一次只发送 1 个? 看来我确实有 ssl 方面的工作。虽然我收到 SSLHandshake Failed 消息,但我通过绕过我的问题中的 ssl 成功连接。我认为它有时只起作用的原因是由于github.com/AFNetworking/AFNetworking/issues/…

以上是关于iOS 8 在我的应用程序中断开了 SSL 连接 - CFNetwork SSLHandshake failed (-9806)的主要内容,如果未能解决你的问题,请参考以下文章

使用 alamofire 通过 iOS 应用程序连接 Windows SSL 服务器

如何检测 socket.io 上的断开连接?

对等体断开连接后未释放SSL内存

Socket io客户端在react-native应用程序中不断断开和重新连接

Tokbox iOS:电话锁定时视频通话断开

Socket.io SSL 连接与 Nginx 和 Express