AFNetWorking3.0使用 自签名证书的https请求
前几日,项目组出于安全角度的考虑,要求项目中的请求使用https请求,因为是企业内部使用的app,因此使用了自签名的证书,而自签名的证书是不受信任的,所以我们就需要自己来做证书的验证,包括服务器验证客户端的证书和我们要信任服务器的证书,SSL双向认证的原理我这里就不赘述了,这里提供两篇博客
iOS安全系列之一:HTTPS: http://oncenote.com/2014/10/21/Security-1-HTTPS/
iOS安全系列之二:HTTPS进阶: http://oncenote.com/2015/09/16/Security-2-HTTPS2/
从开始准备到调试成功一共用了两天,查阅了很多网上提供的解决办法,最后发现很多解决办法都缺少了一个很重要的过程,就是将客户端的证书发送到服务器,让服务器验证我们的身份.如果没有这一步,那么我们的请求就会直接被服务器拒绝导致请求失败.
话不多说,相信说多了也没人看..[手动滑稽]直接上代码,我这里用了afn3.0
准备工作:
首先要导入两个证书, 是两个 一个是客户端使用的.p12的证书,另外一个是服务器端的.cer的证书,将这两个证书拖入工程中,注意要添加target
然后要配置ATS,ATS的配置我也提供一篇博客
iOS 10 适配 ATS: http://www.jianshu.com/p/36ddc5b009a7
新建一个类,继承AFHTTPSessionManager, 我这里重写了initWithURL
- 1 - (instancetype)initWithBaseURL:(NSURL *)url {
- 2 self = [super initWithBaseURL:url];
- 3 if (self) {
- 4
- 5 self.requestSerializer.timeoutInterval = 25;
- 6 [self.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
- 7 [self.requestSerializer setValue:url.absoluteString forHTTPHeaderField:@"Referer"];
- 8
- 9 self.securityPolicy = [self getFreeCustomSecurityPolicy];
- 10
- 11 self.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
- 12 self.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
- 13
- 14 [self setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {
- 15 NSLog(@"setSessionDidBecomeInvalidBlock error : %@",error);
- 16 }];
- 17 if ([url.absoluteString hasPrefix:@"https"]) {//当请求是https时,我们就需要做
- 18 __weak typeof(self) weakSelf = self;
- 19 [self setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing _Nullable * _Nullable credential) {
- 20 NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
- 21 __autoreleasing NSURLCredential * credentialSelf =nil;
- 22 if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {//如果有受信任的证书,如果是自签名的证书,这里会是NSURLAuthenticationMethodClientCertificate
- 23 if([weakSelf.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
- 24 credentialSelf = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
- 25 if(credentialSelf) {
- 26 disposition = NSURLSessionAuthChallengeUseCredential;
- 27 } else {
- 28 disposition = NSURLSessionAuthChallengePerformDefaultHandling;
- 29 }
- 30 } else {
- 31 disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
- 32 }
- 33 } else {//当接收到的是NSURLAuthenticationMethodClientCertificate,我们就将我们的证书发送给服务器让其验证我们的身份
- 34 // client authentication
- 35 SecIdentityRef identity = NULL;
- 36 SecTrustRef trust = NULL;
- 37 NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];
- 38 NSFileManager *fileManager =[NSFileManager defaultManager];
- 39 if(![fileManager fileExistsAtPath:p12])
- 40 {
- 41 NSLog(@"client.p12:not exist");
- 42 } else {
- 43 NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
- 44
- 45 if ([weakSelf extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
- 46 {
- 47 SecCertificateRef certificate = NULL;
- 48 SecIdentityCopyCertificate(identity, &certificate);
- 49 const void*certs[] = {certificate};
- 50 CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
- 51 credentialSelf =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
- 52 disposition = NSURLSessionAuthChallengeUseCredential;
- 53 }
- 54 }
- 55 }
- 56 *credential = credentialSelf;
- 57 return disposition;
- 58 }];
- 59 }
- 60 }
- 61 return self;
- 62 }
- 63 - (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
- 64 OSStatus securityError = errSecSuccess;
- 65 //client certificate password
- 66 NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"password" forKey:(__bridge id)kSecImportExportPassphrase];
- 67 CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
- 68 securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);
- 69
- 70 if(securityError == 0) {
- 71 CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
- 72 const void*tempIdentity =NULL;
- 73 tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
- 74 *outIdentity = (SecIdentityRef)tempIdentity;
- 75 const void*tempTrust =NULL;
- 76 tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
- 77 *outTrust = (SecTrustRef)tempTrust;
- 78 } else {
- 79 NSLog(@"Failedwith error code %d",(int)securityError);
- 80 return NO;
- 81 }
- 82 return YES;
- 83 }
- 84 - (AFSecurityPolicy *)getFreeCustomSecurityPolicy {
- 85 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
- 86 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
- 87 NSData *certData = [NSData dataWithContentsOfFile:cerPath];
- 88 NSSet *certificateSet = [[NSSet alloc] initWithObjects:certData, nil];
- 89 [securityPolicy setAllowInvalidCertificates:YES];
- 90 [securityPolicy setPinnedCertificates:certificateSet];
- 91 [securityPolicy setValidatesDomainName:NO];
- 92
- 93 return securityPolicy;
- 94 }
这样设置好了之后就可以发送使用自签名证书的https请求了
希望可以帮助到遇到自签名证书无法发送请求的同学
代码不太优雅,轻喷,如有错误的地方欢迎指正
邮箱:masterLiPeng@163.com
AFNetWorking3.0使用 自签名证书的https请求的更多相关文章
- iOS 用自签名证书实现 HTTPS 请求的原理
在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...
- iOS使用自签名证书实现HTTPS请求
概述 在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求. 默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向 ...
- 超级简单的retrofit使用自签名证书进行HTTPS请求的教程
1. 前言 HTTPS越来越成为主流,谷歌从 2017 年起,Chrome 浏览器将也会把采用 HTTP 协议的网站标记为「不安全」网站:苹果从 2017 年 iOS App 将强制使用 HTTPS: ...
- SpringBoot服务间使用自签名证书实现https双向认证
SpringBoot服务间使用自签名证书实现https双向认证 以服务server-one和server-two之间使用RestTemplate以https调用为例 一.生成密钥 需要生成server ...
- curl wget 不验证证书进行https请求【转】
$ wget 'https://x.x.x.x/get_ips' --no-check-certificate $ curl 'https://x.x.x.x/get_ips' -k 转自 curl ...
- 生成自签名证书-开启https
1.生成CA证书 # 生成 CA 私钥 openssl genrsa -out ca.key 2048 # X.509 Certificate Signing Request (CSR) Manage ...
- iOS 的三种自建证书方法https请求相关配置
如果你的app服务端安装的是SLL颁发的CA,可以使用系统方法直接实现信任SSL证书,关于Apple对SSL证书的要求请参考:苹果官方文档CertKeyTrustProgGuide 这种方式不需要在B ...
- Android 7.0解决抓取不到https请求的问题
问题:Android7.0系统,使用fiddler不能抓取https请求 解决方法: 1.在源码res目录下新建xml目录,增加network_security_config.xml文件 (工程名/ ...
- tomcat使用自签名证书实现https加密访问
部署好java环境和tomcat之后 执行以下语句 #生成证书,keytool是java工具命令,-genkey生成证书,-alias证书名称,-keyalg应该是指算法,-keystore是证书存储 ...
随机推荐
- activiti参考5-任务TASK
一.概要 1,设计TASK的表主要是:ACT_RU_TASK,ACT_HI_TASKINST(见参考-activiti表): 2,任务主要有:人工任务(usertask),服务任务(serviceta ...
- where group by联合使用
where group by联合使用 select 列a,聚合函数 from 表名 where 过滤条件 group by 列a having 过滤条件 group by 字句也和where条件语 ...
- 如何在VMware虚拟机间建立共享磁盘?
在同一台电脑上,有时难免要安装多个虚拟机,存储空间就成了最大的问题,那么如何解决虚拟机的硬盘问题呢,Vmware自带的工具可以很好的解决此问题,下面我们就来看看如何在Vmware虚拟机间建立共享磁盘? ...
- SmartGit STUDY 2
The Index The Index is an intermediate cache for preparing a commit. With SmartGit, you can make hea ...
- Codeforces Round #214 (Div. 2) c题(dp)
C. Dima and Salad time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- xtraTabControl 如何遍历每个选项卡 z
XtraTabHitInfo hi = tabPositionControl.CalcHitInfo(new Point(e.X, e.Y)); if (hi.HitTest == XtraTabHi ...
- ZOJ 2599 Graduated Lexicographical Ordering (数位DP)
首先要吐两行槽:看到集训队论文上有这道题,由于数位DP一律写成记忆化搜索形式的强迫症,就没去看论文上的几个函数是什么……:结果被这道题虐的脑细胞死光……,最后是用随机数据对拍AC程序然后发现BUG改掉 ...
- OpenERP中的会计凭证
OpenERP在采购和销售过程中会自动生成一些会计凭证,这些会计凭证反映了物流和资金流在财务上的处理方式. 仓库入库时 借:库存商品 贷:在途物资 收到供应商发票时 借:在途物资 借:进项税额 贷:应 ...
- Java核心 --- 枚举
Java核心 --- 枚举 枚举把显示的变量与逻辑的数字绑定在一起在编译的时候,就会发现数据不合法也起到了使程序更加易读,规范代码的作用 一.用普通类的方式实现枚举 新建一个终态类Season,把构造 ...
- Java 分割文件 注意事项
public static void main(String args[]) throws Exception { if (args.length < 1) { System.exit(0); ...