iOS適配https詳解

  立刻就要元旦了,網上流傳元旦以後蘋果會對全部的app進行https的驗證,聽說會拒絕全部沒有使用https的app。可是後來又據說是咱們開發者誤解了,元旦事後仍是會支持http,不過開發者須要說明爲何不用https。不過躲得過初一躲不過十五,仍是早點適配https好些啊。而後弄了幾天找了好多博客和文檔,才暫時解決了這個問題。所謂https,只不過是在http的基礎上增長了ssl層的驗證(這樣說不是很準確),也就是在原來的數據包的基礎上加密了一下,然而加密的工做不須要咱們開發者來作,只需在對的位置作好證書的驗證就好了。其實我對ssl層理解也不深,想着之後有時間必定要把網絡這一塊掌握,否則下次碰到這種問題仍是很差解決。廢話很少說,仍是先看看代碼吧。安全

  首先是對NSURLConnection的適配,不論是原生的仍是AF的,歸根結底都是要用它去鏈接服務器。服務器

  1.若是使用AF進行網絡數據請求,那麼使用以下方法便可:網絡

 1 - (AFSecurityPolicy*)customSecurityPolicy
 2 
 3 {
 4     //先導入證書
 5     //在這加證書,通常狀況適用於單項認證
 6     NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ailian" ofType:@"cer"];//證書的路徑
 7 
 8     NSData *certData = [NSData dataWithContentsOfFile:cerPath];
 9     if (certData==nil) {
10         return nil;
11     }
12     // AFSSLPinningModeCertificate 使用證書驗證模式
13     
14     AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
15     
16     // allowInvalidCertificates 是否容許無效證書(也就是自建的證書),默認爲NO
17     
18     // 若是是須要驗證自建證書,須要設置爲YES
19     
20     securityPolicy.allowInvalidCertificates = YES;
21     
22     //validatesDomainName 是否須要驗證域名,默認爲YES;
23     
24     //假如證書的域名與你請求的域名不一致,需把該項設置爲NO;如設成NO的話,即服務器使用其餘可信任機構頒發的證書,也能夠創建鏈接,這個很是危險,建議打開。
25     
26     //置爲NO,主要用於這種狀況:客戶端請求的是子域名,而證書上的是另一個域名。由於SSL證書上的域名是獨立的,假如證書上註冊的域名是www.google.com,那麼mail.google.com是沒法驗證經過的;固然,有錢能夠註冊通配符的域名*.google.com,但這個仍是比較貴的。
27     
28     //如置爲NO,建議本身添加對應域名的校驗邏輯。
29     
30     securityPolicy.validatesDomainName = NO;
31     
32     securityPolicy.pinnedCertificates = @[certData];
33     
34     return securityPolicy;
35     
36 }

  其實,在這裏不須要使用服務器的證書,本人親測過。不過爲了保險起見仍是加上,還須要注意一點,AF3.0須要用到der格式的證書。session

  而後加上下面的代碼:app

  _manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:[self getHostURL]]];ide

      [_manager setSecurityPolicy:[self customSecurityPolicy]];google

  2.若是是原生的NSURLConnection,那麼須要在NSURLConnectionDelegate的一個方法裏面加代碼,以下:加密

 1 - (void)connection:(NSURLConnection *)connection
 2 willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
 3 {
 4     NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
 5     //導入證書       NSLog(@"thePath===========%@",thePath);
 6     NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
 7     CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
 8     
 9     SecIdentityRef identity = NULL;
10     // extract the ideneity from the certificate
11     [self extractP12Data:inPKCS12Data toIdentity:&identity];
12     
13     SecCertificateRef certificate = NULL;
14     SecIdentityCopyCertificate (identity, &certificate);
15     
16     const void *certs[] = {certificate};
17     //                        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
18     // create a credential from the certificate and ideneity, then reply to the challenge with the credential
19     //NSLog(@"identity=========%@",identity);
20     NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent];
21     
22     //           credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
23     
24     [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
25 }          

  接下來是對NSURLSession的適配,如今公認更好的網絡請求類,支持後臺的數據下載和上傳,並且自身是安全的。然而,在使用NSURLSession時須要在一個代理方法裏配置ssl證書。以下:spa

 1 - (void)URLSession:(NSURLSession *)session
 2 didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 3  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
 4 {
 5     NSString *method = challenge.protectionSpace.authenticationMethod;
 6     if([method isEqualToString:NSURLAuthenticationMethodServerTrust]){
 7         NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
 8         completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
 9         return;
10     }
11     NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
12     NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
13     CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
14     SecIdentityRef identity;
15     // 讀取p12證書中的內容
16     OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
17     if(result != errSecSuccess){
18     completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
19         return;
20     }
21     SecCertificateRef certificate = NULL;
22     SecIdentityCopyCertificate (identity, &certificate);
23     const void *certs[] = {certificate};
24     CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
25     NSURLCredential *credential1 = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
26     completionHandler(NSURLSessionAuthChallengeUseCredential, credential1);
27 }
 1 - (OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
 2     OSStatus securityError = errSecSuccess;
 3     CFStringRef password = CFSTR("clientepass");
 4     const void *keys[] = { kSecImportExportPassphrase };
 5     const void *values[] = { password };
 6     CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
 7     CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
 8     securityError = SecPKCS12Import(inP12Data, options, &items);
 9     if (securityError == 0) {
10         CFDictionaryRef ident = (CFDictionaryRef)CFArrayGetValueAtIndex(items,0);
11         const void *tempIdentity = NULL;
12         tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
13         *identity = (SecIdentityRef)tempIdentity;
14     }
15     if (options) {
16         CFRelease(options);
17     }
18     return securityError;
19 }

  其實適配https沒有咱們想象的那麼複雜,你找對了地方可能幾分鐘就弄好了,找不到,可能花幾天。無論怎樣,最後適配成功仍是要感謝網上的一些大神,雖然官網上面也有答案,但畢竟時間不等人,等我研究透徹,估計蘋果又會有新的東西出來吧。至此,但願能幫到正在爲https適配而憂傷的小夥伴們。代理

相關文章
相關標籤/搜索