iOS之https请求客户端---AFNetworking
来源:互联网 发布:历史上真实的和珅 知乎 编辑:程序博客网 时间:2024/05/19 17:03
说点什么
自从出了iOS 9.0之后,Apple要求使用更安全的协议HTTPS,刚开始我们还可以通过在info.plist文件里添加键值对:
App Transport Security Settings ( Dictionary )
Allow Arbitrary Loads – YES ( BOOL )
来继续使用http请求,但是在2017年1月1日后,所有上架的APP必须使用HTTPS,到时候再这么设置就不管用了。
接下来说下我的解决方案及遇到的问题以供大家参考。
首先要确保服务器支持HTTPS,关于服务器的配置推荐参考这篇文章:服务器相关设置,亲测有效哦!
上干货
准备工作:
单向认证只需要 根证书,双向认证还需要一个 客户端证书 (单向双向的区别注意看代码里的注释哦)检测服务器是否符合ATS要求:安装 根证书 到钥匙串,然后在终端输入nscurl --ats-diagnostics --verbose https://你的请求链接如果都符合的话,result 都是pass,哪一项不符合就让服务器修改哪项,当然能不能请求到数据还有其他因素,因为我之前全部都是pass,但是还不能得到数据,因为证书有问题;
1 后台GG会给你一个.crt文件(根证书),和一个client.p12文件(客户端证书),我们需要把.crt格式的根证书转换成我们用的.cer格式。(有人说只能识别der格式,纯属误人子弟!)
格式转换方法:双击.crt文件安装根证书到钥匙串,然后右键选择导出为.cer。
2把导出的.cer根证书和client.p12客户端证书一起拖到项目中,注意勾选相应的target
- 使用第三方AFNetworking3.1.0
先对AFNetworking做个小小的封装:
新建一个继承于 AFHTTPSessionManager 的类 HttpsNetworking,使用此类时直接用
HttpsNetworking manager = [HttpsNetworking getManager];
代替原来的
AFHTTPSessionManager manager = [HttpsNetworking manager] ;
其他的不做任何改变!
下面是分别看一下各个方法的作用及实现
+(HttpsNetworking *)getManager;
代替AFHTTPSessionManager的类方法 manager
+(HttpsNetworking *)getManager{ //调用父类的方法manager获得一个网络请求对象 HttpsNetworking * manager=[HttpsNetworking manager]; //设置manager的securityPolicy manager.securityPolicy=[self policy]; //如果是双向认证则重写NSURLSesson的代理方法(取消下面的注释就可以)// [self setSessionDidReceiveAuthenticationChallengeWithManager:manager]; return manager;}
+(AFSecurityPolicy *)policy;
这个方法就是对证书的一些相关设置
+ (AFSecurityPolicy *)policy{ //根证书路径 NSString * path = [[NSBundle mainBundle] pathForResource:@"根证书" ofType:@"cer"]; // NSData * cerData = [NSData dataWithContentsOfFile:path]; // NSSet * dataSet = [NSSet setWithObject:cerData]; //AFNetworking验证证书的object,AFSSLPinningModeCertificate参数决定了验证证书的方式 AFSecurityPolicy * policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:dataSet]; //是否可以使用自建证书(不花钱的) policy.allowInvalidCertificates=YES; //是否验证域名(一般不验证) policy.validatesDomainName=NO; return policy;}
下面两个方法是双向认证需要实现的,如果你只做单向认证的话可以不看了
+(void)setSessionDidReceiveAuthenticationChallengeWithManager:(AFHTTPSessionManager *)manager ;
双向认证会走这个方法两次,分别验证服务器和客户端
+ (void)setSessionDidReceiveAuthenticationChallengeWithManager:(AFHTTPSessionManager *)manager{ __weak typeof(manager)weakManager = manager; __weak typeof(self)weakSelf = self; [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) { NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __autoreleasing NSURLCredential *credential =nil; if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSLog(@"验证服务器1"); if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { NSLog(@"验证服务器2"); credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; if(credential) { NSLog(@"验证服务器3"); disposition =NSURLSessionAuthChallengeUseCredential; } else { NSLog(@"验证服务器4"); disposition =NSURLSessionAuthChallengePerformDefaultHandling; } } else { NSLog(@"验证服务器5"); disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; } } else { NSLog(@"验证客户端1"); // client authentication 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 { NSLog(@"验证客户端2"); NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12]; if ([[weakSelf class]extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]) { NSLog(@"验证客户端3"); 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; } } } *_credential = credential; return disposition; }];}
+(BOOL)extractIdentity:(SecIdentityRef)outIdentity andTrust:(SecTrustRef )outTrust fromPKCS12Data:(NSData *)inPKCS12Data ;
真正验证客户端证书
+ (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data { OSStatus securityError = errSecSuccess; //客户端证书密码 NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"123456" 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;}
现在你就可以请求https开头的链接啦!
使用示例:
HttpsNetworking *manager = [HttpsNetworking getManager]; [manager GET:[FormalUrl stringByAppendingString:homeHttp] parameters:parameterDic progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@",error); }];
遇到的问题
code=-1206,
如果遇到这个错误请后台GG检查服务器
1、必须支持传输层安全(TLS)协议1.2以上版本
2、证书必须使用SHA256或更高的哈希算法签名
3、必须使用2048位以上RSA密钥或256位以上ECC算法等等
4、证书必须是V3版本
都要满足条件才行
Demmo下载地址
- iOS之https请求客户端---AFNetworking
- iOS AFNetworking Https请求
- ios AFNetworking支持https请求
- ios AFNetworking支持https请求
- iOS AFNetworking 配置Https请求
- iOS AFNetWorking HTTPS自签名证书请求
- AFNetworking https 请求
- iOS开发中使用AFNetWorking进行https请求
- iOS网络-NSURLSession/AFNetworking发送HTTPS网络请求
- iOS开发:对于AFNetworking HTTP转HTTPS请求证书问题
- iOS网络-NSURLSession/AFNetworking发送HTTPS网络请求
- iOS网络-NSURLSession/AFNetworking发送HTTPS网络请求
- iOS基于AFNetworking使用自签名证书实现HTTPS请求
- iOS客户端校验https网络请求证书
- IOS AFNetworking https
- ios AFNetworking https 认证
- AFNetWorking之HTTPS使用
- ios AFNetworking网络请求
- json表单回填(表单反序列化回填值)
- Bootstrap carousel轮转图的使用实例详解
- PHP之等价变换
- iOS 10 本地推送UNUserNotificationCenter
- tomcat 远程调试
- iOS之https请求客户端---AFNetworking
- android studio 添加assets文件夹
- getline()函数详解
- CTF Web php://filter文件内容包含漏洞
- Java堆内存设置原理
- 关闭浏览器驱动命令
- 简单注册页面
- 自定义注解
- nginx 重启