ios https單向驗證


版權聲明:本文為博主原創文章,未經博主允許不得轉載。

https是http+tls。是在http和tcp之間添加了一層ssl加密驗證,ssl將http發送的信息在將要發到傳輸層時進行了加密,同樣數據從傳輸層到達http層時需要ssl解密。

如果iOS通過https訪問的站點(服務器)證書是ca機構頒發的話,不需要多余的代碼,請求以前http的時候怎么寫現在還怎么寫,只是把請求url的http改成https,但是如果站點的證書是自簽證書(如通過java keytool自生成),ios默認是驗證不通過的,請求會失敗,那么需要在http請求回調里面做兩步多余的處理,回調如下:

//證書驗證處理
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
//信任自簽證書站點
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;

具體代碼:

 1 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
 2     if (([challenge.protectionSpace.authenticationMethod
 3           isEqualToString:NSURLAuthenticationMethodServerTrust])) {
 4         if ([challenge.protectionSpace.host isEqualToString:TRUSTED_HOST]) {//TRUSTED_HOST主機名
 5             NSLog(@"Allowing bypass...");
 6             NSURLCredential *credential = [NSURLCredential credentialForTrust:
 7                                            challenge.protectionSpace.serverTrust];
 8             [challenge.sender useCredential:credential
 9                  forAuthenticationChallenge:challenge];
10         }
11     }
12     [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
13 }
14 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
15 {
16     return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
17 }
View Code

 

這兩個回調相當於做了https請求的全局設置,設置的作用是信任該站點的證書,一般在第一次發https請求的時候設置信任,以后客戶端就可以和服務端正常地進行https通信了。

ios原生和uiwebview h5發送https請求的問題都可以通過上面代碼處理uiwebview一樣對不信任證書站點會訪問失敗,原生里面做了對該站點的信任后對h5同樣有效,也就是說一旦原生http請求對該站點信任則h5對該站點的訪問也會正常。在stackoverflow上面看到一個例子,就是只有uiwebview控件需要對不信任證書站點訪問的一種處理方式,既在uiviewview第一次發送https請求的時候在回調里面取消掉這次請求,既在shouldStartLoadWithRequest這個uiwebview回調的時候返回no,並同時用原生http去請求這個地址,並處理回調
設置信任后在原生請求即將收到信息回復的時候(即didReceiveResponse)取消掉該請求,並讓uiwebview重新請求。這樣信任了站點以后uiwebview請求該站點都可以成功。具體代碼來自stackoverflow(http://stackoverflow.com/questions/11573164/uiwebview-to-view-self-signed-websites-no-private-api-not-nsurlconnection-i):

 1 #pragma mark - Webview delegate
 2 
 3 // Note: This method is particularly important. As the server is using a self signed certificate,
 4 // we cannot use just UIWebView - as it doesn't allow for using self-certs. Instead, we stop the
 5 // request in this method below, create an NSURLConnection (which can allow self-certs via the delegate methods
 6 // which UIWebView does not have), authenticate using NSURLConnection, then use another UIWebView to complete
 7 // the loading and viewing of the page. See connection:didReceiveAuthenticationChallenge to see how this works.
 8 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
 9 {
10     NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authenticated);
11 
12     if (!_authenticated) {
13         _authenticated = NO;
14 
15         _urlConnection = [[NSURLConnection alloc] initWithRequest:_request delegate:self];
16 
17         [_urlConnection start];
18 
19         return NO;
20     }
21 
22     return YES;
23 }
24 
25 
26 #pragma mark - NURLConnection delegate
27 
28 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
29 {
30     NSLog(@"WebController Got auth challange via NSURLConnection");
31 
32     if ([challenge previousFailureCount] == 0)
33     {
34         _authenticated = YES;
35 
36         NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
37 
38         [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
39 
40     } else
41     {
42         [[challenge sender] cancelAuthenticationChallenge:challenge];
43     }
44 }
45 
46 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
47 {
48     NSLog(@"WebController received response via NSURLConnection");
49 
50     // remake a webview call now that authentication has passed ok.
51     _authenticated = YES;
52     [_web loadRequest:_request];
53 
54     // Cancel the URL connection otherwise we double up (webview + url connection, same url = no good!)
55     [_urlConnection cancel];
56 }
57 
58 // We use this method is to accept an untrusted site which unfortunately we need to do, as our PVM servers are self signed.
59 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
60 {
61     return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
62 }
View Code

單向驗證的原理網上很多,大致流程就是客戶端第一次發送https請求到服務端,服務端將證書發送給客戶端,該證書包含了公鑰和證書的信息,客戶端進行證書驗證,驗證頒發機構是否合法,是否過期,加密方式等。如果驗證成功則生成一個隨機值(秘鑰),該值用來和服務端進行對稱加密通信,並用公鑰加密,發送給服務端。服務器用證書里的私鑰解密獲得客戶端的密鑰,然后服務端和客戶端就可以進行https通信了。
個人認為ssl的處理邏輯是客戶端會將驗證后生成的秘鑰保存在本地的某文件里,並在客戶端發送https請求時從文件里讀取密鑰並用證書規定的加密方式加密,然后發送給傳輸層傳輸。

 

AFNetwork添加證書驗證

    // /先導入證書
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];//證書的路徑
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
    // AFSSLPinningModeCertificate 使用證書驗證模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    
    // allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認為NO
    // 如果是需要驗證自建證書,需要設置為YES
    securityPolicy.allowInvalidCertificates = YES;
    securityPolicy.validatesDomainName = NO;
    
    securityPolicy.pinnedCertificates = @[certData];

 

使用Keytool生成證書:

1、為服務器生產證書:

keytool -genkey -keyalg RSA -dname "cn=127.0.0.1,ou=inspur,o=none,l=hunan,st=changsha,c=cn" -alias server -keypass 111111 -keystore server.keystore -storepass 111111 -validity 3650

cn改成你服務器地址

 l:省份

st:城市

2、生成csr

csr是用於提交CA認證的文件

keytool -certReq -alias server -keystore server.keystore -file ca.csr

3、生成cer

生成的ca.cer文件用於客戶端證書導入信任服務器

keytool -export -alias server -keystore server.keystore -file ca.cer -storepass 111111

4、tomcat配置

<Connector SSLEnabled="true" clientAuth="false"
        maxThreads="150" port="8443"
        protocol="org.apache.coyote.http11.Http11Protocol"
        scheme="https" secure="true" sslProtocol="TLS"
        keystoreFile="/User/xxx/server.keystore" keystorePass="111111"/>

keystoreFile為文件路徑

配置好后,重啟tomcat可以使用https訪問web工程,端口8443。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM