NSURLSession使用TLS 1.2使用SSL页面失败

时间:2016-02-08 22:02:00

标签: ios objective-c ssl ios9

我正在使用NSULConnection通过SSL将数据发送到Web服务。服务器使用通配符证书(* .mydomain.com)进行签名。证书使用RES SHA256和TLS 1.2,并由CA签名。我正在尝试使用以下代码发送数据:

NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
[req setTimeoutInterval:60];
[req setHTTPMethod:@"POST"];
// ... Set content type and add data to body ... //

[req setURL:@"https://subdomain.mydomain.com/service/"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSLog(@"Starting Upload");
NSURLSessionDataTask *task = [session dataTaskWithRequest:req
                                        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
    // .. Handle Completion .. //
}];

[task resume];

当我运行上面的代码时,我得到以下输出。

CFNetwork SSLHandshake failed (-9801) 
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)

所以,我尝试添加此帖中解释的例外:CFNetwork SSLHandshake failed iOS 9

但是没有运气来解决错误。然后我切换到使用http而不是https,同时留下上面解释的配置更改,它确实有效。然而,这远非理想的解决方案。 http适用于测试,但此应用将处理需要SSL的数据。如何让SSL工作?

修改

以下是在我的服务网址的nscurl --ats-diagnostics版本上运行https的结果

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

Default ATS Secure Connection
---
ATS Default Connection
Result : PASS
---

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

Allowing Arbitrary Loads

---
Allow All Loads
Result : PASS
---

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

Configuring TLS exceptions for ****

---
TLSv1.2
Result : PASS
---

---
TLSv1.1
Result : PASS
---

---
TLSv1.0
Result : PASS
---

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

Configuring PFS exceptions for ****

---
Disabling Perfect Forward Secrecy
Result : PASS
---

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

Configuring PFS exceptions and allowing insecure HTTP for ****

---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
Result : PASS
---

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

Configuring TLS exceptions with PFS disabled for ****

---
TLSv1.2 with PFS disabled
Result : PASS
---

---
TLSv1.1 with PFS disabled
Result : PASS
---

---
TLSv1.0 with PFS disabled
Result : PASS
---

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

Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for ****

---
TLSv1.2 with PFS disabled and insecure HTTP allowed
Result : PASS
---

---
TLSv1.1 with PFS disabled and insecure HTTP allowed
Result : PASS
---

---
TLSv1.0 with PFS disabled and insecure HTTP allowed
Result : PASS
---

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

修改2

以下是我添加的例外情况:

<dict>
    <key>mydomain.com</key>
    <dict>
        <key>NSIncludesSubdomains</key>
        <true/>
        <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
        <true/>
        <key>NSTemporaryExceptionMinimumTLSVersion</key>
        <string>1.0</string>
        <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
        <false/>
    </dict>
</dict>

curl -v

的结果
*   CAfile: /opt/local/share/curl/curl-ca-bundle.crt
  CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* Server certificate:
*    subject: C=XXX; ST=XXX; L=XXX; O=XXX; CN=*.mydomain.com
*    start date: 2015-08-17 00:00:00 GMT
*    expire date: 2018-11-14 12:00:00 GMT
*    subjectAltName: subdomain.mydomain.com matched
*    issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
*    SSL certificate verify ok.

openssl s_client -connect

的结果
CONNECTED(00000003)
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=XXX/ST=XXX/L=XXX/O=XXX/CN=*.mydomain.com
   i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
 1 s:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
.
.
.
-----END CERTIFICATE-----
subject=/C=XXX/ST=XXX/L=XXX/O=XXX/CN=*.mydomain.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 3033 bytes and written 490 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-SHA384
    Session-ID: XXX
    Session-ID-ctx: 
    Master-Key: XXX
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1454971371
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

2 个答案:

答案 0 :(得分:0)

Verify return code: 20 (unable to get local issuer certificate)

看起来DigiCert Root CA未在本地计算机上正确加载。打开KeyChain Access App,检查它是否在Login或System Roots部分。

答案 1 :(得分:0)

answer节省了我的一天!事实证明,ATS要求服务器必须支持密码套件here中列出的密码。我可以确认建议的修复有效。