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)

用户喜欢...

为了提高效率 - 如何将双向功率流集成到UPS设计中(第2部分)

在本系列的第1部分中,我讨论了如何将双向功率流集成到不间断电源(UPS)设计中。在第二部分中,我将更详细地介绍用于UPS和电池备份应用的2kW,48V至400V, 93%效率,隔离双向DC / DC转换器参...


为了提高效率 - 如何将双向功率流集成到UPS设计中(第1部分)

随着对更紧凑,更小和更高效的电力系统的日益重视,对双向转换器的兴趣日益增加。能够双向功率流的双向DC / DC转换器可以将传统上用于电池充电和备份操作所需的两个DC / DC转换器组合成一...


Java性能调优的11个实用技巧

下面有几个很容易遵循的建议和最佳实践能够帮你创建一个性能良好的应用程序。...


[原创] TI TIDA-00951 2kW UPS电源双向DC变换参考设计

TI公司的TIDA-00951是2kW UPS电源双向DC/DC转换器参考设计,工作电压从36 到 60V电池组和300到400-V DC总线,效率大于93%,通信接...


IDT P9242-R3+P9221-R3 15W双向数据通信无线充电解决方案

IDT公司的P9242-R3是高度集成15W磁感应无线功率发送器,具有双向数据通信,包括了32位ARM Cortex-M0处理器,外部物体检测(F...


实用的技巧,使您的电子项目更容易

selina 在 周二, 10/31/2017 - 10:36 提交 好像不久以前(哦,但是这是)我在我的第一个入门电路课。我发现电路理论非常有趣...和乏味...令人沮丧。但是当我在面包板上建立了第一个电路时,我被...


GSI实现在SigmaQuad-IIIe SRAM和UltraScale FPGAs之间7.2Gbyte/sec的双向数据传输

微处理器快速读取内存,双倍和四倍的数据速率同步SRAM,网络和电信系统的快速数据交换,用于支持高端数位讯号处理器以及其在VoIP、蜂巢式基站台、DSL线卡及数据机等方面的应用,低延迟...


鸡肋还是实用 网红护眼仪真的有效吗?

随着科技产品发展的越来越先进,人们每天面对电脑、手机、平板等这类数码设备的时间也越来越长,可是这种液晶...


Littelfuse新推高温Alternistor三端双向可控硅简化热管理并抑制高浪涌

Littelfuse, Inc.,作为全球电路保护领域的领先企业,今日宣布推出两个系列的高温Alternistor三端双向可控硅,成为该公...


Intersil 推出业内首款USB-C降压-升压稳压器

全球领先的半导体解决方案供应商瑞萨电子株式会社子公司Intersil近日宣布,推出业内首款针对使用可反转USB Type-...