版權聲明:本文爲博主原創文章,未經博主容許不得轉載。java
https是http+tls。是在http和tcp之間添加了一層ssl加密驗證,ssl將http發送的信息在將要發到傳輸層時進行了加密,一樣數據從傳輸層到達http層時須要ssl解密。ios
若是iOS經過https訪問的站點(服務器)證書是ca機構頒發的話,不須要多餘的代碼,請求之前http的時候怎麼寫如今還怎麼寫,只是把請求url的http改爲https,可是若是站點的證書是自簽證書(如經過java keytool自生成),ios默認是驗證不經過的,請求會失敗,那麼須要在http請求回調裏面作兩步多餘的處理,回調以下:web
//證書驗證處理 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; //信任自簽證書站點 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
具體代碼:apache
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 }
這兩個回調至關於作了https請求的全局設置,設置的做用是信任該站點的證書,通常在第一次發https請求的時候設置信任,之後客戶端就能夠和服務端正常地進行https通訊了。api
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):tomcat
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 }
單向驗證的原理網上不少,大體流程就是客戶端第一次發送https請求到服務端,服務端將證書發送給客戶端,該證書包含了公鑰和證書的信息,客戶端進行證書驗證,驗證頒發機構是否合法,是否過時,加密方式等。若是驗證成功則生成一個隨機值(祕鑰),該值用來和服務端進行對稱加密通訊,並用公鑰加密,發送給服務端。服務器用證書裏的私鑰解密得到客戶端的密鑰,而後服務端和客戶端就能夠進行https通訊了。
我的認爲ssl的處理邏輯是客戶端會將驗證後生成的祕鑰保存在本地的某文件裏,並在客戶端發送https請求時從文件裏讀取密鑰並用證書規定的加密方式加密,而後發送給傳輸層傳輸。服務器
AFNetwork添加證書驗證iview
// /先導入證書 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生成證書:tcp
一、爲服務器生產證書:ide
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:城市
二、生成csr
csr是用於提交CA認證的文件
keytool -certReq -alias server -keystore server.keystore -file ca.csr
三、生成cer
生成的ca.cer文件用於客戶端證書導入信任服務器
keytool -export -alias server -keystore server.keystore -file ca.cer -storepass 111111
四、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。