在APP內做HTTPS請求后,使用NSURLConnection
或NSURLSession
都會接收到信任相關的方法回調,做進一步的處理。
因為在https的通信過程里,請求方需要使用對方證書生成一個隨機的加密秘鑰,用來做之后請求數據的加密。核心問題就是對方的證書是不是可信任的,所以就有了上面iOS請求回調的方法。
//NSURLSession的回調方法
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
這個方法結束內部最后需要調用參數里的completionHandler
,把證書和處置方式傳遞回去。
而NSURLConnection
稍微不同,它的委托回調里,實現- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
方法,然后在方法里調用5種處理方法之一:
In this method,you must invoke one of the challenge-responder methods (NSURLAuthenticationChallengeSender
protocol):
關于證書,一種是從機構簽發授權的CA證書,一種是自己生成的證書。證書有一個授權鏈,A授權B,B授權C,然后有一個是根證書。在操作系統里會有受信任的根證書列表,iOS系統的可以查看iOS 中可用的受信任根證書列表。如果根證書是信任的,那么它的授權鏈里所有證書都通過驗證。所以對于CA證書,如果它的根證書是操作系統本身信任的,那么就可以讓系統做驗證。
用電腦瀏覽器做請求的時候可以直觀的看到,用chrome打開HTTPS網站,然后開發者工具查看security,點擊view certificate,就可以看到證書的授權鏈:
在鑰匙串里的系統根證書就可以看到操作系統信任的根證書。
順帶看了下12306的問題,用的是自己做的根證書Sinorail Certification Authority,不是系統默認信任的那些機構,所以第一次打開總會看到瀏覽器的警告。瀏覽器為什么警告?為了提醒用戶,因為有可能這是一個釣魚網站+假的ssl證書。而現在一般的情況是大家都養成了繼續請求、忽略警告的習慣。
OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType * __nullable result)
是檢測的核心方法,會從當前證書沿著授權鏈驗證到根證書。
而如果是自己建的ssl證書,那么就要在APP內加入和服務器相同的證書,使用證書文件來做驗證,在請求HTTPS回調后,驗證服務端的證書和我們本地的證書是否數據一致。考慮到授權鏈的問題,APP內的證書可能和服務端返回的證書是一個父子關系,所以需要把服務端的證書的授權鏈里所有證書都獲取到后,依次和APP本地的證書做校驗。
不過這樣似乎有個問題,就是你的證書會暴露在你的APP文件里,如果把APP通過電腦下載下來,拿到ipa文件就可以解壓拿到里面的.cer證書了!
不過剛才看了下iTunes,新版本竟然去掉了APP Store,點擊應用全部都跳轉到網頁,而網頁沒有下載功能!