1

我正在使用 aUIWebView在我的 iOS 应用程序中加载网站。在更新到 iOS 9 并相应地构建应用程序后,网站仍然可以从我的服务器加载正常,但无法从 cdnjs 加载引导程序的 css 和 js 文件(例如https://cdnjs.cloudflare.com/ajax/libs/twitter-引导/3.3.5/css/bootstrap.min.css)。

我认为这与新的 ATS 有关,但到目前为止,我无法弄清楚为什么它无法从 cdnjs 加载文件(它们支持 TLS 1.2 和大量现代密码)而且我没有可用于测试的带有 nscurl 的 El Capitan cdnjs(请参阅https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)。

4

1 回答 1

2

nscurl为你在 El Capitan 上运行了一个。根据结果​​,问题是 cdnjs 不支持前向保密,因此您必须为 cdnjs.cloudflare.com 添加一个例外并设置NSAppTransportSecurity为 false。

更新:以下几行就足够了:

  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSExceptionDomains</key>  
    <dict>  
      <key>cdnjs.cloudflare.com</key>  
      <dict>  
        <key>NSExceptionRequiresForwardSecrecy</key><false/>  
      </dict>  
    </dict>
  </dict>

有关详细信息,请参阅下面的日志:

nscurl --ats-diagnostics --verbose https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css
Starting ATS Diagnostics

Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css.
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
================================================================================

Default ATS Secure Connection
---
ATS Default Connection
ATS Dictionary:
{
}
2015-09-29 14:59:16.983 nscurl[490:10186] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrust 0x7f7f89e052f0 [0x7fff7c50f890]>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<SecCertificate 0x7f7f89e04570 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89e04950 [0x7fff7c50f890]>"
), NSUnderlyingError=0x7f7f8b8059b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrust 0x7f7f89e052f0 [0x7fff7c50f890]>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<SecCertificate 0x7f7f89e04570 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89e04950 [0x7fff7c50f890]>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorFailingURLStringKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorClientCertificateStateKey=0}
---

================================================================================

Allowing Arbitrary Loads

---
Allow All Loads
ATS Dictionary:
{
    NSAllowsArbitraryLoads = true;
}
Result : PASS
---

================================================================================

Configuring TLS exceptions for cdnjs.cloudflare.com

---
TLSv1.2
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
        };
    };
}
2015-09-29 14:59:17.140 nscurl[490:10186] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrust 0x7f7f89f136f0 [0x7fff7c50f890]>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<SecCertificate 0x7f7f89f12b20 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89f12d60 [0x7fff7c50f890]>"
), NSUnderlyingError=0x7f7f8b804160 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrust 0x7f7f89f136f0 [0x7fff7c50f890]>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<SecCertificate 0x7f7f89f12b20 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89f12d60 [0x7fff7c50f890]>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorFailingURLStringKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorClientCertificateStateKey=0}
---

---
TLSv1.1
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
        };
    };
}
2015-09-29 14:59:17.170 nscurl[490:10186] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrust 0x7f7f89c2a2a0 [0x7fff7c50f890]>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<SecCertificate 0x7f7f89c47750 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89c45c90 [0x7fff7c50f890]>"
), NSUnderlyingError=0x7f7f8b9029d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrust 0x7f7f89c2a2a0 [0x7fff7c50f890]>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<SecCertificate 0x7f7f89c47750 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f89c45c90 [0x7fff7c50f890]>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorFailingURLStringKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorClientCertificateStateKey=0}
---

---
TLSv1.0
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
        };
    };
}
2015-09-29 14:59:17.206 nscurl[490:10186] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrust 0x7f7f8b905230 [0x7fff7c50f890]>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<SecCertificate 0x7f7f8b904590 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f8b9047d0 [0x7fff7c50f890]>"
), NSUnderlyingError=0x7f7f89d5fce0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrust 0x7f7f8b905230 [0x7fff7c50f890]>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<SecCertificate 0x7f7f8b904590 [0x7fff7c50f890]>",
    "<SecCertificate 0x7f7f8b9047d0 [0x7fff7c50f890]>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorFailingURLStringKey=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css, NSErrorClientCertificateStateKey=0}
---

================================================================================

Configuring PFS exceptions for cdnjs.cloudflare.com

---
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

================================================================================

Configuring PFS exceptions and allowing insecure HTTP for cdnjs.cloudflare.com

---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

================================================================================

Configuring TLS exceptions with PFS disabled for cdnjs.cloudflare.com

---
TLSv1.2 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.1 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.0 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

================================================================================

Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for cdnjs.cloudflare.com

---
TLSv1.2 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.1 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "cdnjs.cloudflare.com" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

================================================================================
于 2015-09-29T13:29:59.377 回答