
情況說明:用post方法加載一個(gè)h5頁面,請(qǐng)求的url為https的,web服務(wù)器掛的證書是自建證書,報(bào)錯(cuò):
2018-03-17 11:50:09.341674+0800 ICBCPayDemo[2216:1514635] TIC SSL Trust Error [7:0x1c01729c0]: 3:0
2018-03-17 11:50:09.542477+0800 ICBCPayDemo[2216:1514635] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
2018-03-17 11:50:09.543400+0800 ICBCPayDemo[2216:1514635] Task .<0> HTTP load failed (error code: -1202 [3:-9813])
2018-03-17 11:50:09.545843+0800 ICBCPayDemo[2216:1514343] NSURLConnection finished with error - code -1202
2018-03-17 11:50:09.554470+0800 ICBCPayDemo[2216:1514273] didFailLoadWithError:Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “ebankp-pay-agn.sdc.cs.icbc” which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, NSErrorPeerCertificateChainKey=
幾種解決方式:
第一種:使用私有API,擴(kuò)展NSURLRequest
? ??????只要填上這些就直接能用


第二種:生成.cer格式的證書,添加到工程中(未親測(cè))
? ? ? ? 方法來源:http://www.jb51.net/article/132096.html
? ??????1. 雙擊證書,這時(shí)證書已經(jīng)添加到了鑰匙串中
? ??????2. 將cer 文件拖入工程中
? ??????3. 如果使用的是AFNetwotking 的話,在代碼中添加以下代碼
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
?//證書
?AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
?manager.securityPolicy = securityPolicy;
// 2.設(shè)置證書模式
?NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"tomcat" ofType:@"cer"]; //tomcat是cer文件的名稱
?NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
?manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:cerData, nil]];
?// 客戶端是否信任非法證書
?manager.securityPolicy.allowInvalidCertificates = YES;
?// 是否在證書域字段中驗(yàn)證域名
?[manager.securityPolicy setValidatesDomainName:NO];
????????但這個(gè)cer文件不知道能不能導(dǎo)出來,沒找到mac版chrome的導(dǎo)出方法,windows導(dǎo)出方式看:https://wdd.js.org/export-https-certificate-in-browser.html
? ? ? ? 這個(gè)導(dǎo)出方式看起來靠譜點(diǎn)兒,但也沒試,感覺應(yīng)該由環(huán)境配置人員去搞:http://www.cocoachina.com/ios/20160928/17663.html
第三:
自建證書,將證書導(dǎo)入工程(其實(shí)沒有自建證書怎么導(dǎo)入工程啊哈)
-?(void)viewDidLoad?{
????[superviewDidLoad];
????//導(dǎo)入客戶端證書
????NSString?*cerPath?=?[[NSBundle?mainBundle]?pathForResource:@"ca"ofType:@"cer"];
????NSData?*data?=?[NSData?dataWithContentsOfFile:cerPath];
????SecCertificateRef?certificate?=?SecCertificateCreateWithData(NULL,?(__bridge?CFDataRef)?data);
????self.trustedCerArr?=?@[(__bridge_transfer?id)certificate];
????//發(fā)送請(qǐng)求
NSURL?*testURL?=?[NSURL?URLWithString:@"https://casetree.cn/web/test/demo.php"];
????NSURLSession?*session?=?[NSURLSession?sessionWithConfiguration:[NSURLSessionConfiguration?defaultSessionConfiguration]?delegate:self?delegateQueue:[NSOperationQueue?mainQueue]];
????NSURLSessionDataTask?*task?=?[session?dataTaskWithRequest:[NSURLRequest?requestWithURL:testURL]];
????[task?resume];
????//?Do?any?additional?setup?after?loading?the?view,?typically?from?a?nib.
}
#pragma?mark?-?NSURLSessionDelegate
-?(void)URLSession:(NSURLSession?*)session?didReceiveChallenge:(NSURLAuthenticationChallenge?*)challenge
?completionHandler:(void?(^)(NSURLSessionAuthChallengeDisposition?disposition,?NSURLCredential?*?__nullable?credential))completionHandler{
????OSStatus?err;
????NSURLSessionAuthChallengeDisposition?disposition?=?NSURLSessionAuthChallengePerformDefaultHandling;
????SecTrustResultType??trustResult?=?kSecTrustResultInvalid;
????NSURLCredential?*credential?=?nil;
????//獲取服務(wù)器的trust?object
????SecTrustRef?serverTrust?=?challenge.protectionSpace.serverTrust;
????//將讀取的證書設(shè)置為serverTrust的根證書
????err?=?SecTrustSetAnchorCertificates(serverTrust,?(__bridge?CFArrayRef)self.trustedCerArr);
????if(err?==?noErr){
????????//通過本地導(dǎo)入的證書來驗(yàn)證服務(wù)器的證書是否可信,如果將SecTrustSetAnchorCertificatesOnly設(shè)置為NO,則只要通過本地或者系統(tǒng)證書鏈任何一方認(rèn)證就行
????????err?=?SecTrustEvaluate(serverTrust,?&trustResult);
????}
????if(err?==?errSecSuccess?&&?(trustResult?==?kSecTrustResultProceed?||?trustResult?==?kSecTrustResultUnspecified)){
????????//認(rèn)證成功,則創(chuàng)建一個(gè)憑證返回給服務(wù)器
????????disposition?=?NSURLSessionAuthChallengeUseCredential;
????????credential?=?[NSURLCredential?credentialForTrust:serverTrust];
????}
????else{
????????disposition?=?NSURLSessionAuthChallengeCancelAuthenticationChallenge;
????}
????//回調(diào)憑證,傳遞給服務(wù)器
????if(completionHandler){
????????completionHandler(disposition,?credential);
????}
}
不能解決問題的方式:
第一:
寫進(jìn)plist還是報(bào)錯(cuò)

相關(guān)知識(shí)點(diǎn):
簡單的來說,SSL/TSL通過四次握手,主要交換三個(gè)信息:
1. 數(shù)字證書:該證書包含了公鑰等信息,一般是由服務(wù)器發(fā)給客戶端,接收方通過驗(yàn)證這個(gè)證書是不是由信賴的CA簽發(fā),或者與本地的證書相對(duì)比,來判斷證書是否可信;假如需要雙向驗(yàn)證,則服務(wù)器和客戶端都需要發(fā)送數(shù)字證書給對(duì)方驗(yàn)證;
2. 三個(gè)隨機(jī)數(shù)
3. 加密通信協(xié)議
驗(yàn)證證書的API
相關(guān)的Api在Security Framework中,驗(yàn)證流程如下:
1). 第一步,先獲取需要驗(yàn)證的信任對(duì)象(Trust Object)。這個(gè)Trust Object在不同的應(yīng)用場(chǎng)景下獲取的方式都不一樣,對(duì)于NSURLConnection來說,是從delegate方法-connection:willSendRequestForAuthenticationChallenge:回調(diào)回來的參數(shù)challenge中獲取([challenge.protectionSpace serverTrust])。
2). 使用系統(tǒng)默認(rèn)驗(yàn)證方式驗(yàn)證Trust Object。SecTrustEvaluate會(huì)根據(jù)Trust Object的驗(yàn)證策略,一級(jí)一級(jí)往上,驗(yàn)證證書鏈上每一級(jí)數(shù)字簽名的有效性(上一部分有講解),從而評(píng)估證書的有效性。
3). 如第二步驗(yàn)證通過了,一般的安全要求下,就可以直接驗(yàn)證通過,進(jìn)入到下一步:使用Trust Object生成一份憑證([NSURLCredential credentialForTrust:serverTrust]),傳入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])處理,建立連接。
4). 假如有更強(qiáng)的安全要求,可以繼續(xù)對(duì)Trust Object進(jìn)行更嚴(yán)格的驗(yàn)證。常用的方式是在本地導(dǎo)入證書,驗(yàn)證Trust Object與導(dǎo)入的證書是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation,這一部分在講解AFNetworking源碼中會(huì)講解到。
5). 假如驗(yàn)證失敗,取消此次Challenge-Response Authentication驗(yàn)證流程,拒絕連接請(qǐng)求。
ps: 假如是自建證書的,則會(huì)跳過第二步,使用第三部進(jìn)行驗(yàn)證,因?yàn)樽越ㄗC書的根CA的數(shù)字簽名未在操作系統(tǒng)的信任列表中。
搭建完HTTPS服務(wù)器之后,可以使用nscurl命令來進(jìn)行檢測(cè),查看建立的HTTPS服務(wù)器是否能通過ATS特性。
1nscurl?--ats-diagnostics?--verbose?https://casetree.cn
那么,如何本地導(dǎo)入證書進(jìn)行驗(yàn)證呢??
在這里先提一下,由于iOS客戶端支持的證書是DER格式的,我們需要?jiǎng)?chuàng)建客戶端證書。創(chuàng)建客戶端證書,直接將服務(wù)端的CA根證書導(dǎo)出成DER格式就行。
1openssl??x509??-inform?PEM??-outform?DER?-inca.crt?-out?ca.cer
另外也有說:把服務(wù)器給你的自簽證的證書放入bundle一般是.cer文件