公司使用https悬秉,但是與后臺調(diào)試接口的時候卻死活調(diào)試失敗。我在Safari打開他們的接口和泌,發(fā)現(xiàn)證書不匹配的警告,于是就判定是他們證書配置有問題梯皿,后來發(fā)現(xiàn)果然是這個問題县恕。
總結(jié)下iOS使用https的問題
用HTTPS有個問題,就是CA證書忠烛。缺省情況下,iOS要求連接的HTTPS站點必須為CA簽名過的合法證書美尸,AFNetworking是個iOS上常用的HTTP訪問庫,由于它是基于iOS的HTTP網(wǎng)絡(luò)通訊庫恕酸,自然證書方面的要求和系統(tǒng)是一致的胯陋,也就是你需要有一張合法的站點證書。
正式的CA證書非常昂貴惶岭,很多人都知道犯眠,AFNetworking2只要通過下面的代碼,你就可以使用自簽證書來訪問HTTPS
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
securityPolicy.allowInvalidCertificates = YES;
這么做有個問題鸯旁,就是你無法驗證證書是否是你的服務(wù)器后端的證書,給中間人攻擊铺罢,即通過重定向路由來分析偽造你的服務(wù)器端打開了大門。
瀏覽器中https驗證流程###
1 客戶端輸入網(wǎng)址https://www.domain..com缩滨,連接到server的443端口泉瞻。
2 服務(wù)器返回一個證書(包含公鑰、和證書信息侧巨,如證書的頒發(fā)機構(gòu)鞭达,過期時間等),證書由服務(wù)器所擁有的私鑰非對稱加密生成畴蹭。
3 客戶端對證書進行驗證(首先會驗證證書是否有效,比如頒發(fā)機構(gòu)桨踪,過期時間等等)芹啥。
4 如果客戶端驗證通過,客戶端生成一個隨機數(shù)墓怀,在用服務(wù)器返回的證書(公鑰)進行加密傳輸。
5 因為公鑰是通過服務(wù)器的私鑰生成虱朵,所以服務(wù)器是可以對客戶端的傳回的加密數(shù)據(jù)進行對稱解密的钓账。服務(wù)器拿到由客戶端生成的隨機數(shù),對要傳遞的數(shù)據(jù)使用隨機數(shù)加密梆暮。
6 客戶端收到服務(wù)器使用隨機數(shù)加密的數(shù)據(jù)進行解密啦粹。
不過在app的開發(fā)中因為我們的app通常只需要和一個服務(wù)器端進行交互窘游,所以不必要每次請求都從服務(wù)器那邊獲取證書(公鑰)跳纳,在開發(fā)中app直接將服務(wù)器對應(yīng)生成的證書(公鑰)放在沙盒中,HTTPS請求時只要直接和服務(wù)器返回的證書(公鑰)進行比對寺庄。如果驗證通過則使用公鑰進行加密在傳遞回服務(wù)器。
這樣即使app中的證書(公鑰)被截取饶深,中間人使用證書冒充了服務(wù)器與客戶端進行通信時(通過了驗證)逛拱,但因為從app返回的數(shù)據(jù)都是通過證書(公鑰)加密的。而中間人從app截取的證書時公鑰朽合,缺少對應(yīng)的私鑰即使截獲了信息也無法解密曹步。能夠最大的程度的保護傳遞的信息安全。
從上面的通信過程中讲婚,最重要的是存儲在服務(wù)器的私鑰。因為只有私鑰生成了在通信過程中傳遞的證書(公鑰)活合,且只有通過私鑰才能對公鑰加密的信息進行解密物赶,所以在開發(fā)過程中保護好私鑰的安全。
代碼介紹:
/**
SSL身份認證
@return
*/
+ (AFSecurityPolicy *)customSecurityPolicy{
// 導(dǎo)入證書 僅支持cer 格式 需要將crt格式轉(zhuǎn)換下 //轉(zhuǎn)換格式 openssl x509 -in 你的證書.crt -out 你的證書.cer -outform der
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"2__.gongfupay.com" ofType:@"cer"];
NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
// AFSSLPinningModeCertificate 使用證書驗證模式
// AFSSLPinningModeNone 這個模式表示不做SSL pinning告嘲,只跟瀏覽器一樣在系統(tǒng)的信任機構(gòu)列表里驗證服務(wù)端返回的證書奖地。若證書是信任機構(gòu)簽發(fā)的就會通過,若是自己服務(wù)器生成的證書就不會通過参歹。
// AFSSLPinningModeCertificate 這個模式表示用證書綁定方式驗證證書,需要客戶端保存有服務(wù)端的證書拷貝缸血,這里驗證分兩步械筛,第一步驗證證書的域名有效期等信息,第二步是對比服務(wù)端返回的證書跟客戶端返回的是否一致笆豁。
// AFSSLPinningModePublicKey 這個模式同樣是用證書綁定方式驗證赤赊,客戶端要有服務(wù)端的證書拷貝,只是驗證時只驗證證書里的公鑰抛计,不驗證證書的有效期等信息。只要公鑰是正確的瘦陈,就能保證通信不會被竊聽波俄,因為中間人沒有私鑰,無法解開通過公鑰加密的數(shù)據(jù)懦铺。
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
// allowInvalidCertificates 是否允許無效證書(也就是自建的證書)冬念,默認為NO 如果是需要驗證自建證書,需要設(shè)置為YES
securityPolicy.allowInvalidCertificates = YES;
//是否需要驗證域名急前,默認為YES
//假如證書的域名與你請求的域名不一致,需把該項設(shè)置為NO统求;如設(shè)成NO的話据块,即服務(wù)器使用其他可信任機構(gòu)頒發(fā)的證書,也可以建立連接另假,這個非常危險,建議打開己莺。
//置為NO,主要用于這種情況:客戶端請求的是子域名阵子,而證書上的是另外一個域名胜蛉。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com誊册,那么mail.google.com是無法驗證通過的;當然君旦,有錢可以注冊通配符的域名*.google.com嘲碱,但這個還是比較貴的。
//如置為NO悍汛,建議自己添加對應(yīng)域名的校驗邏輯离咐。
securityPolicy.validatesDomainName = NO;
[securityPolicy setPinnedCertificates:@[cerData]];
return securityPolicy;
}
AFHTTPSessionManager
調(diào)用setSecurityPolicy
方法 進行身份驗證