本文由我們團隊的美女 超哥 分享
HTTPS從最終的數據解析的角度,與HTTP相同钾埂。HTTPS將HTTP協(xié)議數據包放到SSL/TSL層加密后科平,在TCP/IP層組成IP數據報去傳輸,以此保證傳輸數據的安全瞪慧;而對于接收端,在SSL/TSL將接收的數據包解密之后氨菇,將數據傳給HTTP協(xié)議層妓湘。
SSL/TSL包括四次握手,主要交換三個信息:
- 數字證書豌研;
- 三個隨機數唬党;
- 加密通訊協(xié)議。
其通訊過程如下示意圖:
數字證書
該證書一般是由服務器發(fā)給客戶端,接收方通過驗證這個證書是不是由信賴的CA簽發(fā)屯烦,或者與本地的證書相對比房铭,來判斷證書是否可信;假如需要雙向驗證缸匪,則服務器和客戶端都需要發(fā)送數字證書給對方驗證。
數字證書的生成是分層級的露懒,從葉節(jié)點證書往根證書層層驗證(有效期、簽名等等)蛇耀,遇到根證書時坎弯,發(fā)現作為可信錨點的它存在與可信證書列表中,那么驗證就通過撩炊。例如在鑰匙串中可以看到某券商公司申請的證書沒有在系統(tǒng)可信任的證書列表中崎脉。
下面以?某浪sdk里的證書為代表簡單說明一下數字證書的內容:
證書字段 | 證書說明 |
---|---|
簽發(fā)者名稱 | 發(fā)布并簽署該證書的實體的信息 |
序列號 | 數字證書機構(Certificate Authority, CA)給證書的唯一整數荧嵌,一個數字證書一個序列號 |
主題名稱 | 用于識別該數字證書的信息 |
公共密鑰信息 | 可公開的密鑰信息 |
簽名 | 通過簽名算法計算證書內容后得到的數據,用于驗證證書是否被篡改 |
三個隨機數
這三個隨機數構成了后續(xù)通信過程中用來對數據進行對稱加密解密的“對話密鑰”谭网。首先客戶端先發(fā)第一個隨機數n1赃春,然后服務器返回第二個隨機數n2(這個過程同時把數字證書發(fā)給客戶端),這兩個隨機數都是明文的锥涕;而第三個隨機數n3狭吼,客戶端用數字證書的公鑰進行非對稱加密破花,發(fā)給服務器疲吸;而服務器用只有自己知道的私鑰來解密摘悴,獲取第三個隨機數。服務端和客戶端都有了三個隨機數n1+n2+n3后蹂喻,兩端就使用這三個隨機數來生成“對話密鑰”捂寿,在此之后的通信就使用這個“對話密鑰”來進行對稱加解密挫以。
加密通信協(xié)議
雙方商量具體使用哪一種加密方式,假如兩者支持的加密方式不匹配踱侣,則無法進行通信大磺。因為這個過程中,服務端的私鑰只用來解密第三個隨機數待榔,從來沒有在網絡中傳輸過流济,只要私鑰沒有被泄露,那么數據就是安全的雕憔。
下邊主要介紹一下NSURLConnection
支持HTTPS的實現設置證書作為可信的錨點代碼應用糖声。
// SDWebImageDownloaderOperation
(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
//通過 challenge.protectionSpace.authenticationMethod 取得保護空間要求我們認證的方式
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates) &&
[challenge.sender respondsToSelector:@selector(performDefaultHandlingForAuthenticationChallenge:)]) {
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
} else {
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
} else {
if ([challenge previousFailureCount] == 0) {
if (self.credential) {
[[challenge sender] useCredential:self.credential forAuthenticationChallenge:challenge];
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
}
StockPromotionViewController
在webview
中使用
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString* scheme = [[request URL] scheme];
//判斷是不是https
if ([scheme isEqualToString:@"https"])
{
if (self.authed)
{
return YES;
}
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:request.URL] delegate:self];
[conn start];
[webView stopLoading];
return NO;
}
return YES;
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount]== 0)
{
self.authed = YES;
//NSURLCredential 這個類是表示身份驗證憑據不可變對象蘸泻。憑證的實際類型聲明的類的構造函數來確定〔⑸龋回調中會收到一個challenge
NSURLCredential* cre = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:cre forAuthenticationChallenge:challenge];
}
}
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
{
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.authed = YES;
//webview 重新加載請求抡诞。
[self.webView loadRequest:[NSURLRequest requestWithURL:connection.currentRequest.URL]];
[connection cancel];
}