close
当前位置: 物联网在线 > 技术文库 > ios >

iOS实用篇:Https双向认证

年前的时候,关于苹果要强制https的传言四起,虽然结果只是一个“谣言”,但是很明显的这是迟早会到来的,间接上加速了各公司加紧上https的节奏,对于iOS客户端来说,上https需不需要改变一些东西取决于---------对,就是公司有没有钱。土豪公司直接买买买,iOS开发者只需要把http改成https完事。然而很不幸,我们在没钱的公司,选择了自签证书。虽然网上很多关于https的适配,然而很多都是已过时的,这里我们主要是讲一下https双向认证。

【证书选择】自签

【网络请求】原生NSURLSession或者AFNetworking3.0以上版本

【认证方式】双向认证

Https双向认证过程

先来了解一下双向认证的大体过程:(图片来自网络,如果是某位博主原创的请私信我)

iOS实用篇:Https双向认证

httpsLine.png

下面我们一步步来实现

1、设置服务端证书

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、处理挑战

原生的NSURLSession是在

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

代理方法里面处理挑战的,再看看AFNetworking在该代理方法里处理的代码

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

我们只需要给它传递一个处理的block

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

根据传来的challenge生成disposition(应对挑战的方式)和credential(客户端生成的挑战证书)

3、服务端认证

当challenge的认证方法为NSURLAuthenticationMethodServerTrust时,需要客户端认证服务端证书

//评估服务端安全性 if([weakSelf.afnetworkingManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { //创建凭据 credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; if(credential) { disposition =NSURLSessionAuthChallengeUseCredential; } else { disposition =NSURLSessionAuthChallengePerformDefaultHandling; } } else { disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; }

4、客户端认证

认证完服务端后,需要认证客户端

由于是双向认证,这一步是必不可省的

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的一致,注意最后需要调用

completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

来执行回调操作

关于UIWebView的Https双向认证

网上的资料大体上有几种解决方法

1:跳过Https认证(这还能跳过?没试过,不太靠谱)


(责任编辑:ioter)

用户喜欢...

Littelfuse新推出具有较低断态电压的80A离散型双向瞬态抑制二极管

Littelfuse今天推出了SP11xx系列双向瞬态抑制二极管(SPA®二极管)中的最新产品——80A离散型双向瞬态抑制二极管。 SP1103C系列80A离散型双向瞬态抑制二极管可为电路设计师提供更低的断态电压...


日本物联网农业技术展开实用化实验

日本为争夺物联网事业主导权,积极推动相关事业,在农业应用方面,继日立制作所在2017年7月宣布将在哥伦比亚推动...


为提高效率——如何将双向功率流集成到UPS设计中

随着对更紧凑和更高效电力系统的日益重视,双向转换器越来越受到关注。具有双向功率流的双向DC/DC换流器可将电...


Littelfuse新推出具有较低断态电压的80A离散型双向瞬态抑制二极管,用于保护低压电源总线

Littelfuse, Inc.,作为全球电路保护领域的领先企业,今天推出了SP11xx系列双向瞬态抑制二极管(SPA二极管)中的最新产...


如何将双向功率流集成到UPS设计中(第一部分)

随着对更紧凑和更高效电力系统的日益重视,双向转换器越来越受到关注。具有双向功率流的双向DC/DC换流器可将电池充电和备份操作传统上所需的两个DC/DC换流器组合在一起,降低了整个系...


调查:家用机器人东西方偏好大不同,欧美偏实用、中国重育儿、日本卡哇伊

家用型机器人有5大应用领域,分别为家事、娱乐休闲、老人照护及身障辅助、个人移动工具、居家监控。...


通过 STM32CubeMX 生成 HID 双向通讯工程

客户在做 USB 通讯的时候,基本的需求就是发送某些数据到 USB host 端,同时接收一些数据从 USB Host 端,那么如何快速的建立一个工程并验证数据是否正确呢?下边我们就结合 STM32F072 的评估板...


[原创] TI 2kW不间断电源(UPS)双向转换器参考设计TIDA-00951

TI公司的TIDA-00951是2kW 48V-400V效率大于93%的绝缘双向DC/DC转换器参考设计,数字控制,工作范围从36V-60V电池和300-400V DC总线...


盘点目前实用性最强的智能家居产品

从家的装修风格最能体现主人的品,如果您选择智能的居,给您分享几款功能强大、实用、有趣的智能家居。...


未来你想要的智能家居生活在这里都能找到

我们曾给过未来太多定义,也曾对未来抱有无数幻想。雨果说:未来只属于两种人,一种是思想者,一种是劳动者。...