iOS實用教程之Https雙向認證詳解

前言

站在用戶的角度思考問題,與客戶深入溝通,找到土默特左旗網(wǎng)站設(shè)計與土默特左旗網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設(shè)計、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋土默特左旗地區(qū)。

年前的時候,關(guān)于蘋果要強制https的傳言四起,雖然結(jié)果只是一個“謠言”,但是很明顯的這是遲早會到來的,間接上加速了各公司加緊上https的節(jié)奏,對于iOS客戶端來說,上https需不需要改變一些東西取決于---------對,就是公司有沒有錢。土豪公司直接買買買,iOS開發(fā)者只需要把http改成https完事。然而很不幸,我們在沒錢的公司,選擇了自簽證書。雖然網(wǎng)上很多關(guān)于https的適配,然而很多都是已過時的,這里我們主要是講一下https雙向認證。

【證書選擇】自簽

【網(wǎng)絡(luò)請求】原生NSURLSession或者AFNetworking3.0以上版本

【認證方式】雙向認證

Https雙向認證過程

先來了解一下雙向認證的大體過程:(圖片來自網(wǎng)絡(luò),如果是某位博主原創(chuàng)的請私信我)

iOS實用教程之Https雙向認證詳解

下面我們一步步來實現(xiàn)

1、設(shè)置服務(wù)端證書

 NSString *certFilePath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
 NSData *certData = [NSData dataWithContentsOfFile:certFilePath];
 NSSet *certSet = [NSSet setWithObject:certData];
 AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:certSet];
 policy.allowInvalidCertificates = YES;
 policy.validatesDomainName = NO;
 self.afnetworkingManager.securityPolicy = policy;

2、處理挑戰(zhàn)

原生的NSURLSession是在

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(nonnull NSURLAuthenticationChallenge *)challenge completionHandler:(nonnull void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler

代理方法里面處理挑戰(zhàn)的,再看看AFNetworking在該代理方法里處理的代碼

 if (self.taskDidReceiveAuthenticationChallenge) {
  disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
 } else {
  ...
 }

我們只需要給它傳遞一個處理的block

[self.afnetworkingManager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
  ...
}

根據(jù)傳來的challenge生成disposition(應(yīng)對挑戰(zhàn)的方式)和credential(客戶端生成的挑戰(zhàn)證書)

3、服務(wù)端認證

當(dāng)challenge的認證方法為NSURLAuthenticationMethodServerTrust時,需要客戶端認證服務(wù)端證書

//評估服務(wù)端安全性
if([weakSelf.afnetworkingManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
    //創(chuàng)建憑據(jù)
    credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    if(credential) {
     disposition =NSURLSessionAuthChallengeUseCredential;
    } else {
     disposition =NSURLSessionAuthChallengePerformDefaultHandling;
    }
   } else {
    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
   }

4、客戶端認證

認證完服務(wù)端后,需要認證客戶端

由于是雙向認證,這一步是必不可省的

   SecIdentityRef identity = NULL;
   SecTrustRef trust = NULL;
   NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];
   NSFileManager *fileManager =[NSFileManager defaultManager];

   if(![fileManager fileExistsAtPath:p12])
   {
    NSLog(@"client.p12:not exist");
   }
   else
   {
    NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];

    if ([[weakSelf class]extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
    {
     SecCertificateRef certificate = NULL;
     SecIdentityCopyCertificate(identity, &certificate);
     const void*certs[] = {certificate};
     CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
     credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
     disposition =NSURLSessionAuthChallengeUseCredential;
    }
   }
+ (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
 OSStatus securityError = errSecSuccess;
 //client certificate password
 NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"your p12 file pwd"
                 forKey:(__bridge id)kSecImportExportPassphrase];

 CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
 securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);

 if(securityError == 0) {
  CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
  const void*tempIdentity =NULL;
  tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
  *outIdentity = (SecIdentityRef)tempIdentity;
  const void*tempTrust =NULL;
  tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
  *outTrust = (SecTrustRef)tempTrust;
 } else {
  NSLog(@"Failedwith error code %d",(int)securityError);
  return NO;
 }
 return YES;
}

原生NSURLSession雙向認證

在原生的代理方法里面認證就行,代碼基本和AFNetworking的一致,注意最后需要調(diào)用

 completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

來執(zhí)行回調(diào)操作

關(guān)于UIWebView的Https雙向認證

網(wǎng)上的資料大體上有幾種解決方法

1:跳過Https認證(這還能跳過?沒試過,不太靠譜)

2:中斷原有的請求步驟,將request拿出來,下載完整的HTML代碼,讓webView加載該代碼(在單頁面展示的情況下基本滿足使用,但是在部分標(biāo)簽不是獨立跳轉(zhuǎn)https路徑的時候,將出現(xiàn)無法加載的情況,不是很好用)

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
 NSString * urlString = [request.URL absoluteString];
 if ([urlString containsString:URL_API_BASE]) {
  [[SUHTTPOperationManager manager]REQUEST:request progress:nil handler:^(BOOL isSucc, id responseObject, NSError *error) {
   NSString * htmlString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
   BASE_INFO_FUN(@"下載HTML完畢");
   [self loadHTMLString:htmlString baseURL:nil];
  }];
  return NO;
 }
 return YES;
}

3、中斷原有的請求步驟,將request拿出來,完成鑒權(quán)認證之后,再讓webView重新請求該request(這種方式理論上好像可以,我試過,沒有成功,可能我打開的方式不正確)
4、或許,您有更好的解決方案 - -

關(guān)于代碼

網(wǎng)上很多https雙向認證的代碼,基本是一樣的,這里我們直接拿來用就可以,前提是我們不能單純copy,而是在理解其實現(xiàn)的基礎(chǔ)上,整合到工程中,遇到問題解決思路清晰,而不是一臉懵逼。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。

當(dāng)前文章:iOS實用教程之Https雙向認證詳解
當(dāng)前地址:http://bm7419.com/article32/pcohpc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司、面包屑導(dǎo)航、企業(yè)網(wǎng)站制作、微信小程序、商城網(wǎng)站網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設(shè)計