NSURLSession / NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)子域?

我们的应用在我们的生产环境和开发环境中都能正常工作,但在分段环境中,我们遇到了一些常见错误:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) 

根据我的理解,当您尝试连接到非httpsurl时会发生此错误。

  • 我们使用ngrok为我们的本地隧道有一个httpsurl,工作正常。
  • 对于生产,我们也使用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