AFNetworking3.0 HTTPS請求
最近公司把網路請求從HTTP改成HTTPS 加密 證書這些東西 在這裡整理一下
HTTPS
HTTPS連線建立過程大致是,客戶端和服務端建立一個連線,服務端返回一個證書,客戶端裡存有各個受信任的證書機構根證書,用這些根證書對服務端 返回的證書進行驗證,經驗證如果證書是可信任的,就生成一個pre-master secret,用這個證書的公鑰加密後傳送給服務端,服務端用私鑰解密後得到pre-master secret,再根據某種演算法生成master secret,客戶端也同樣根據這種演算法從pre-master secret生成master secret,隨後雙方的通訊都用這個master secret對傳輸資料進行加密解密。
1.證書是怎樣驗證的?怎樣保證中間人不能偽造證書?
首先要知道非對稱加密演算法的特點,非對稱加密有一對公鑰私鑰,用公鑰加密的資料只能通過對應的私鑰解密,用私鑰加密的資料只能通過對應的公鑰解密。
我們來看最簡單的情況:一個證書頒發機構(CA),頒發了一個證書A,伺服器用這個證書建立https連線。客戶端在信任列表裡有這個CA機構的根證書。
首先CA機構頒發的證書A裡包含有證書內容F,以及證書加密內容F1,加密內容F1就是用這個證書機構的私鑰對內容F加密的結果。(這中間還有一次hash演算法,略過。)
建立https連線時,服務端返回證書A給客戶端,客戶端的系統裡的CA機構根證書有這個CA機構的公鑰,用這個公鑰對證書A的加密內容F1解密得 到F2,跟證書A裡內容F對比,若相等就通過驗證。整個流程大致是:F->CA私鑰加密->F1->客戶端CA公鑰解密->F。 因為中間人不會有CA機構的私鑰,客戶端無法通過CA公鑰解密,所以偽造的證書肯定無法通過驗證。
2.什麼是SSL Pinning?
可以理解為證書繫結,是指客戶端直接儲存服務端的證書,建立https連線時直接對比服務端返回的和客戶端儲存的兩個證書是否一樣,一樣就表明證書 是真的,不再去系統的信任證書機構裡尋找驗證。這適用於非瀏覽器應用,因為瀏覽器跟很多未知服務端打交道,無法把每個服務端的證書都儲存到本地,但CS架 構的像手機APP事先已經知道要進行通訊的服務端,可以直接在客戶端儲存這個服務端的證書用於校驗。
為什麼直接對比就能保證證書沒問題?如果中間人從客戶端取出證書,再偽裝成服務端跟其他客戶端通訊,它傳送給客戶端的這個證書不就能通過驗證嗎?確 實可以通過驗證,但後續的流程走不下去,因為下一步客戶端會用證書裡的公鑰加密,中間人沒有這個證書的私鑰就解不出內容,也就截獲不到資料,這個證書的私 鑰只有真正的服務端有,中間人偽造證書主要偽造的是公鑰。
為什麼要用SSL Pinning?正常的驗證方式不夠嗎?如果服務端的證書是從受信任的的CA機構頒發的,驗證是沒問題的,但CA機構頒發證書比較昂貴,小企業或個人使用者 可能會選擇自己頒發證書,這樣就無法通過系統受信任的CA機構列表驗證這個證書的真偽了,所以需要SSL Pinning這樣的方式去驗證。
3.利用AFNetworking完成HTTPS請求 (AFSecurityPolicy)
首先把證書放在工程的根目錄下
AFNetworking部分
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
securityPolicy.allowInvalidCertificates = YES;
securityPolicy.validatesDomainName = YES;
manager.securityPolicy = securityPolicy;
我遇到的坑:
1.每次請求都崩潰原因是往陣列裡加了空物件
斷點跟程式碼
AFNetworking的AFSecurityPolicy.m裡
for (NSData *certificateData in self.pinnedCertificates) {
[pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
}
在這裡一直崩潰
原因是因為本地的那個證書裡沒有公鑰!!!!
//從本地證書裡取public key
static id AFPublicKeyForCertificate(NSData *certificate) {
id allowedPublicKey = nil;
...
// 這裡的allowedPublicKey 一直是空!!
return allowedPublicKey;
}
換了一個正確的證書之後 這個問題解決了 但是出別的問題
證書總是驗證不過 (本地證書沒問題 伺服器給的公鑰也OK)
if (!AFServerTrustIsValid(serverTrust)) {
return NO;
}
總是返回NO
跟進去
static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
BOOL isValid = NO;
SecTrustResultType result;
__Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out);
//kSecTrustResultUnspecified:證書通過驗證,但使用者沒有設定這些證書是否被信任
//kSecTrustResultProceed:證書通過驗證,使用者有操作設定了證書被信任,例如在彈出的是否信任的alert框中選擇always trust
isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
// 總是返回5 也就是kSecTrustResultRecoverableTrustFailure
_out:
return isValid;
}
原因:是因為Charles的問題!!! 就這個問題糾結了好久 偶然間發現的
參考:
http://www.jianshu.com/p/c6a903da8346
http://my.oschina.net/vimfung/blog/494687
http://www.cocoachina.com/ios/20140916/9632.html
相關文章
- 支援https請求以及https請求的抓包HTTP
- iOS開發 支援https請求以及https請求的抓包iOSHTTP
- jmeter請求https地址JMeterHTTP
- Charles 代理https請求HTTP
- java實現https請求JavaHTTP
- CCHttpClient發起https請求HTTPclient
- 小程式https請求,http網站升到httpsHTTP網站
- 瀏覽器如何將你的http請求轉為https請求?瀏覽器HTTP
- nodejs HTTPS發起POST請求NodeJSHTTP
- Charles 抓取 https 請求說明文件(mac)HTTPMac
- OkHttp關於https請求的設定HTTP
- java|HttpsURLConnection實現https請求JavaHTTP
- 初探計算機網路之HTTPS請求計算機網路HTTP
- nodejs實現HTTPS發起POST請求NodeJSHTTP
- java發http,https請求獲取資料JavaHTTP
- 通過 Apache Commons HttpClient 傳送 HTTPS 請求ApacheHTTPclient
- 使用CloseableHttpClient 訪問 http 和https 的get請求HTTPclient
- iOS 同步請求 非同步請求 GET請求 POST請求iOS非同步
- 騰訊雲:免費SSL證書實現https請求HTTP
- Charles對Android手機Https請求的抓包AndroidHTTP
- Android 網路框架之OKhttp實現https請求Android框架HTTP
- HTTPS請求筆記- SSL安全通道驗證問題HTTP筆記
- SpringMVC中如何傳送GET請求、POST請求、PUT請求、DELETE請求。SpringMVCdelete
- 配置Charles 設定手機代理並允許https請求HTTP
- 利用Fiddler對Android HTTPs請求進行監測AndroidHTTP
- .net 模擬登陸 post https 請求跳轉頁面HTTP
- 關於httpclient 請求https (如何繞過證書驗證)HTTPclient
- 請求框架&移動請求框架
- 『言善信』Fiddler工具 — 15、使用Fiddler抓取HTTPS請求HTTP
- 【Python】用原生的urllib2+httplib請求HttpsPythonHTTP
- 使用charles嗅探https請求,你的API並不安全HTTPAPI
- 請求OpenFeign的GET請求時,請求為何失敗?
- 有趣的請求引數/請求頭
- 大請求、請求超時問題
- 【轉】怎麼用PHP傳送HTTP請求(POST請求、GET請求)?PHPHTTP
- iOS的http/https請求——十分鐘學會Charles抓包iOSHTTP
- 安卓端出現https請求失敗的一次問題排查安卓HTTP
- Moya,KingFisher中使用自簽名證書發起HTTPS請求HTTP