首先,配置https伺服器需要一個證書,這個證書可以從某些機構獲得,也可以自己通過工具生成。
通過某些合法機構生成的證書客戶端不需要進行驗證
這樣的請求不會觸發Apple的相關代理方法 (URLSession:task:didReceiveChallenge:completionHandler:) 所以無論是AFNetWorking還是Alamofire都不需要進行任何處理,即可正常使用。
非合法機構生成的證書或者自制證書
-
AFNetWorking
AFSecurityPolicy分三種驗證模式:
1. AFSSLPinningModeNone:代表客戶端無條件地信任伺服器端返回的證書。你不必將證書跟你的 APP 一起打包。
2. AFSSLPinningModeCertificate:代表客戶端會將伺服器端返回的證書和本地儲存的證書中的【所有內容】,全部進行校驗;如果正確,才繼續進行。
3. AFSSLPinningModePublicKey:代表客戶端會將伺服器端返回的證書與本地儲存的證書中的【PublicKey部分】進行校驗;如果正確,才繼續進行。
注: AFSSLPinningModeCertificate和AFSSLPinningModePublicKey的區別
-
AFSSLPinningModeCertificate 比較安全但也比較麻煩,它會比對你打包的證書跟伺服器的證書是否一致。因為你的證書是跟 APP 一起打包的,這也就代表說如果你的證書過期了或是變動了,你就得出一版新的 APP 而且舊版 APP 的證書就失效了。你也可以在每次 APP 啟動時,就自動連到某個伺服器下載最新的證書,不過此時這個下載連線就會是有風險的。
-
AFSSLPinningModePublicKey 則是隻比對證書裡的 public key,所以即使伺服器證書有所變動,只要 public key 不變,就能通過驗證。
-
所以如果你能確保每個使用者總是使用最新版本的 APP(例如是公司企業內部專用的),那就可以考慮AFSSLPinningModeCertificate,否則的話選擇 AFSSLPinningModePublicKey 是比較實際的作法。
相關屬性解釋及程式碼例子
- 屬性解釋
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; /* allowInvalidCertificates 是否允許無效證書(也就是自建的證書),預設為NO 如果是需要驗證自建證書,需要設定為YES */ securityPolicy.allowInvalidCertificates = YES; /* validatesDomainName 是否需要驗證域名,預設為YES。 假如證書的域名與你請求的域名不一致,需把該項設定為NO 主要用於這種情況:客戶端請求的是子域名,而證書上的 是另外一個域名。因為SSL證書上的域名是獨立的,假如證書上註冊的域名是www.google.com,那麼mail.google.com是無法驗證通過的;當然,有錢可以註冊萬用字元的域名*.google.com,但這個還是比較貴的。 */ securityPolicy.validatesDomainName = NO; /* validatesCertificateChain 是否驗證整個證書鏈,預設為YES 設定為YES,會將伺服器返回的Trust Object上的證書鏈與本地匯入的證書進行對比,這就意味著,假如你的證書鏈是這樣的: GeoTrust Global CA Google Internet Authority G2 *.google.com 那麼,除了匯入*.google.com之外,還需要匯入證書鏈上所有的CA證書(GeoTrust Global CA, Google Internet Authority G2); 如是自建證書的時候,可以設定為YES,增強安全性;假如是信任的CA所簽發的證書,則建議關閉該驗證; */ securityPolicy.validatesCertificateChain = NO; 複製程式碼
- 完整程式碼
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; /* 建立AFSecurityPolicy有兩種方式。 第一種方式是讓AFN在Bundle裡面自動尋找並嘗試匹配。 第二種方式是直接指定證書的位置 */ AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init]; [securityPolicy setAllowInvalidCertificates:NO]; [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; [securityPolicy setValidatesDomainName:YES]; [securityPolicy setValidatesCertificateChain:NO]; NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"name" ofType:@"cer"]; NSData *certData = [NSData dataWithContentsOfFile:cerPath]; AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init]; [securityPolicy setAllowInvalidCertificates:NO]; [securityPolicy setPinnedCertificates:@[certData]]; [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; [securityPolicy setValidatesDomainName:YES]; [securityPolicy setValidatesCertificateChain:NO]; manager.securityPolicy = securityPolicy; 複製程式碼
-
-
Alamofire
ServerTrustPolicy分六種驗證方式
1.performDefaultEvaluation
預設的策略,只有合法證書才能通過驗證
2.performRevokedEvaluation
對登出證書做的一種額外設定,不是很明白這裡,有興趣的朋友可以最近查一下。
3.pinCertificates
代表客戶端會將伺服器端返回的證書和本地儲存的證書中的【所有內容】,全部進行校驗;如果正確,才繼續進行。
4.pinPublicKeys
代表客戶端會將伺服器端返回的證書與本地儲存的證書中的【PublicKey部分】進行校驗;如果正確,才繼續進行。
5.disableEvaluation
該選項下,驗證一直都是通過的,也就是說無條件信任
6.customEvaluation
自定義驗證,需要返回一個布林型別的結果
注: pinPublicKeys和pinCertificates的區別可以參考上面AFN的介紹。
相關引數的介紹
- certificates 證書檔案。ServerTrustPolicy.certificates()方法會在bundle中自動搜尋證書相關檔案的字尾檔案。
- validateCertificateChain 是否驗證證書鏈
- validateHost 是否驗證域名地址。
完整程式碼
這裡最好是封裝一個SessionManger的單例進行統一處理。Swift的https驗證策略,支援一次對多個域名進行設定。
let serverTrustPolicies: [String: ServerTrustPolicy] = [ "test.example.com": .pinCertificates( certificates: ServerTrustPolicy.certificates(), validateCertificateChain: true, validateHost: true ), "insecure.expired-apis.com": .disableEvaluation ] let manger = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)) 複製程式碼
這裡的設定是,針對
test.example.com
域名進行pinCertificates
型別的驗證,並驗證證書鏈和域名地址。 針對insecure.expired-apis.com
域名進行disableEvaluation
型別的驗證。