iOS9的UIWebView中阻止了来自cdnjs.cloudflare.com的文件

iOS9的UIWebView中阻止了来自cdnjs.cloudflare.com的文件,ios,uiwebview,ios9,cdn,app-transport-security,Ios,Uiwebview,Ios9,Cdn,App Transport Security,我正在使用UIWebView在iOS应用程序中加载网站。更新到iOS 9并相应构建应用程序后,网站仍然可以从我的服务器上正常加载,但无法从cdnjs加载引导的css和js文件(例如) 我假设这与新的ATS有关,但到目前为止,我没有弄清楚为什么它无法从cdnjs加载文件(它们支持TLS 1.2和大量现代密码),而且我没有一个带有nscurl的El Capitan可用于测试cdnjs(请参阅)。我在El Capitan上为您运行了一个nscurl。根据结果,问题在于cdnjs不支持前向保密,因此您必

我正在使用
UIWebView
在iOS应用程序中加载网站。更新到iOS 9并相应构建应用程序后,网站仍然可以从我的服务器上正常加载,但无法从cdnjs加载引导的css和js文件(例如)


我假设这与新的ATS有关,但到目前为止,我没有弄清楚为什么它无法从cdnjs加载文件(它们支持TLS 1.2和大量现代密码),而且我没有一个带有nscurl的El Capitan可用于测试cdnjs(请参阅)。

我在El Capitan上为您运行了一个
nscurl
。根据结果,问题在于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>
NSAppTransportSecurity
NSExceptionDomains
cdnjs.cloudflare.com
NSExceptionRequiresForwardSecretary
有关详细信息,请参阅下面的日志:

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
---

================================================================================
nscurl--ats诊断--verbosehttps://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css
启动ATS诊断
配置ATS Info.plist键并将HTTPS加载结果显示给https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css.
如果URLSession:task:didCompleteWithError:返回零错误,则测试将“通过”。
================================================================================
默认ATS安全连接
---
ATS默认连接
ATS字典:
{
}
2015-09-29 14:59:16.983 nscurl[490:10186]NSURLSession/NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)
结果:失败
错误:Error Domain=NSURERRORDOMAIN Code=-1200“发生SSL错误,无法建立到服务器的安全连接。”UserInfo={NSURERRORFAILLINGURLPERTRETERRORKEY=,NSLocalizedRecoverysSuggestion=是否仍要连接到服务器?,\u kCFStreamErrorDomainKey=3,\u kCFStreamErrorCodeKey=-9802,NSERROPERCertificateChainKey==(
"",
""
),NSUnderlyingError=0x7f7f8b8059b0{Error Domain=KCFerrorDomain=KCF网络代码=-1200“(null)”用户信息={{kCFStreamPropertySSLClientCertificateState=0,kCFStreamPropertySSLPeerTrust=,[KCFnetworkCfsstreamsLerOriginalValue=-9802,[kCFStreamErrorDomainKey=3,[kCFStreamErrorCodeKey=-9802,KCFStreamPropertySSLpeertificates=(
"",
""
)}},NSLocalizedDescription=发生SSL错误,无法与服务器建立安全连接。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,NSerrorClientCertificateeStateKey=0}
---
================================================================================
允许任意载荷
---
允许所有负载
ATS字典:
{
NSAllowsArbitraryLoads=true;
}
结果:通过
---
================================================================================
为cdnjs.cloudflare.com配置TLS异常
---
TLSv1.2
ATS字典:
{
NSExceptionDomains={
“cdnjs.cloudflare.com”={
NSExceptionMinimumTLSVersion=“TLSv1.2”;
};
};
}
2015-09-29 14:59:17.140 nscurl[490:10186]NSURLSession/NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)
结果:失败
错误:Error Domain=NSURERRORDOMAIN Code=-1200“发生SSL错误,无法建立到服务器的安全连接。”UserInfo={NSURERRORFAILLINGURLPERTRETERRORKEY=,NSLocalizedRecoverysSuggestion=是否仍要连接到服务器?,\u kCFStreamErrorDomainKey=3,\u kCFStreamErrorCodeKey=-9802,NSERROPERCertificateChainKey==(
"",
""
),NSUnderlyingError=0x7f7f8b804160{Error Domain=KCFerrorDomain=KCF网络代码=-1200“(null)”用户信息={{kCFStreamPropertySSLClientCertificateState=0,kCFStreamPropertySSLPeerTrust=,[KCFnetworkCfsstreamsLerOriginalValue=-9802,[KCFStreamerDomainKey=3,[KCFStreamerCodeKey=-9802,kCFStreamPropertySSLPeerCertificates=(
"",
""
)}},NSLocalizedDescription=发生SSL错误,无法与服务器建立安全连接。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,NSerrorClientCertificateeStateKey=0}
---
---
TLSv1.1
ATS字典:
{
NSExceptionDomains={
“cdnjs.cloudflare.com”={
NSExceptionMinimumTLSVersion=“TLSv1.1”;
};
};
}
2015-09-29 14:59:17.170 nscurl[490:10186]NSURLSession/NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)
结果:失败
错误:Error Domain=NSURERRORDOMAIN Code=-1200“发生SSL错误,无法建立到服务器的安全连接。”UserInfo={NSURERRORFAILLINGURLPERTRETERRORKEY=,NSLocalizedRecoverysSuggestion=是否仍要连接到服务器?,\u kCFStreamErrorDomainKey=3,\u kCFStreamErrorCodeKey=-9802,NSERROPERCertificateChainKey==(
"",
""
),NSUnderlyingError=0x7f7f8b9029d0{Error Domain=kCFErrorDomainCFNetwork Code=-1200“(null)”用户信息={{kCFStreamPropertySSLClientCertificateState=0,kCFStreamPropertySSLPeerTrust=,[KCFnetworkCfsstreamsLerOriginalValue=-9802,[kCFStreamErrorDomainKey=3,[kCFStreamErrorCodeKey=-9802,KCFStreamPropertySlPeerCertificates=-9802=(
"",
""
)}},NSLocalizedDescription=发生SSL错误,无法与服务器建立安全连接。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,NSerrorClientCertificateeStateKey=0}
---
---
TLSv1.0
言语