NSURLSession / NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)子域?
我们的应用在我们的生产环境和开发环境中都能正常工作,但在分段环境中,我们遇到了一些常见错误:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
根据我的理解,当您尝试连接到非https
url时会发生此错误。
- 我们使用ngrok为我们的本地隧道有一个
https
url,工作正常。 - 对于生产,我们也使用
https://ourdomain.com
,它工作正常。 - 为了登台,我们使用
https://staging.ourdomain.com
并且发生错误。
我见过很多解决scheme,说明这样做:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
但是我的雇主反对禁用ATS只是为了升职,他也反对为我们的staging URL
添加例外。
任何想法,为什么我们的登台URL将导致这个错误抛出或如何解决它?
ATS诊断输出:
Starting ATS Diagnostics Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://staging.domain.co. A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error. ================================================================================ Default ATS Secure Connection --- ATS Default Connection ATS Dictionary: { } Result : PASS --- ================================================================================ Allowing Arbitrary Loads --- Allow All Loads ATS Dictionary: { NSAllowsArbitraryLoads = true; } Result : PASS --- ================================================================================ Configuring TLS exceptions for staging.domain.co --- TLSv1.2 ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.2"; }; }; } Result : PASS --- --- TLSv1.1 ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.1"; }; }; } Result : PASS --- --- TLSv1.0 ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.0"; }; }; } Result : PASS --- ================================================================================ Configuring PFS exceptions for staging.domain.co --- Disabling Perfect Forward Secrecy ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- ================================================================================ Configuring PFS exceptions and allowing insecure HTTP for staging.domain.co --- Disabling Perfect Forward Secrecy and Allowing Insecure HTTP ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionAllowsInsecureHTTPLoads = true; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled for staging.domain.co --- TLSv1.2 with PFS disabled ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.2"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- --- TLSv1.1 with PFS disabled ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.1"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- --- TLSv1.0 with PFS disabled ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionMinimumTLSVersion = "TLSv1.0"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for staging.domain.co --- TLSv1.2 with PFS disabled and insecure HTTP allowed ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionAllowsInsecureHTTPLoads = true; NSExceptionMinimumTLSVersion = "TLSv1.2"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- --- TLSv1.1 with PFS disabled and insecure HTTP allowed ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionAllowsInsecureHTTPLoads = true; NSExceptionMinimumTLSVersion = "TLSv1.1"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- --- TLSv1.0 with PFS disabled and insecure HTTP allowed ATS Dictionary: { NSExceptionDomains = { "staging.domain.co" = { NSExceptionAllowsInsecureHTTPLoads = true; NSExceptionMinimumTLSVersion = "TLSv1.0"; NSExceptionRequiresForwardSecrecy = false; }; }; } Result : PASS --- ================================================================================
应用程序传输安全不仅仅是HTTP vs HTTPS。 您需要使用正确configuration的服务器+证书来避免ATS问题。 从苹果文档[1]:
服务器必须至less支持传输层安全性(TLS)协议版本1.2。 连接密码仅限于那些提供前向保密的密码。 证书必须使用SHA256或更高版本的签名散列algorithm进行签名,并使用2048位或更大的RSA密钥或256位或更大的椭圆曲线(ECC)密钥。 无效的证书导致硬故障并且没有连接。
如果您使用OS X 10.11(或更高版本),则可以使用nscurl来排除故障。 打开一个terminal并运行:
/usr/bin/nscurl --ats-diagnostics https://staging.ourdomain.com
[1] https://developer.apple.com/library/ios/technotes/App-Transport-Security-Technote/index.html