iOS适配https详解

  立刻就要元旦了,网上流传元旦以后苹果会对全部的app进行https的验证,听说会拒绝全部没有使用https的app。可是后来又据说是咱们开发者误解了,元旦事后仍是会支持http,不过开发者须要说明为何不用https。不过躲得过初一躲不过十五,仍是早点适配https好些啊。而后弄了几天找了好多博客和文档,才暂时解决了这个问题。所谓https,只不过是在http的基础上增长了ssl层的验证(这样说不是很准确),也就是在原来的数据包的基础上加密了一下,然而加密的工做不须要咱们开发者来作,只需在对的位置作好证书的验证就好了。其实我对ssl层理解也不深,想着之后有时间必定要把网络这一块掌握,否则下次碰到这种问题仍是很差解决。废话很少说,仍是先看看代码吧。安全

  首先是对NSURLConnection的适配,不论是原生的仍是AF的,归根结底都是要用它去链接服务器。服务器

  1.若是使用AF进行网络数据请求,那么使用以下方法便可:网络

 1 - (AFSecurityPolicy*)customSecurityPolicy
 2 
 3 {
 4     //先导入证书
 5     //在这加证书,通常状况适用于单项认证
 6     NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ailian" ofType:@"cer"];//证书的路径
 7 
 8     NSData *certData = [NSData dataWithContentsOfFile:cerPath];
 9     if (certData==nil) {
10         return nil;
11     }
12     // AFSSLPinningModeCertificate 使用证书验证模式
13     
14     AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
15     
16     // allowInvalidCertificates 是否容许无效证书(也就是自建的证书),默认为NO
17     
18     // 若是是须要验证自建证书,须要设置为YES
19     
20     securityPolicy.allowInvalidCertificates = YES;
21     
22     //validatesDomainName 是否须要验证域名,默认为YES;
23     
24     //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其余可信任机构颁发的证书,也能够创建链接,这个很是危险,建议打开。
25     
26     //置为NO,主要用于这种状况:客户端请求的是子域名,而证书上的是另一个域名。由于SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是没法验证经过的;固然,有钱能够注册通配符的域名*.google.com,但这个仍是比较贵的。
27     
28     //如置为NO,建议本身添加对应域名的校验逻辑。
29     
30     securityPolicy.validatesDomainName = NO;
31     
32     securityPolicy.pinnedCertificates = @[certData];
33     
34     return securityPolicy;
35     
36 }

  其实,在这里不须要使用服务器的证书,本人亲测过。不过为了保险起见仍是加上,还须要注意一点,AF3.0须要用到der格式的证书。session

  而后加上下面的代码:app

  _manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:[self getHostURL]]];ide

      [_manager setSecurityPolicy:[self customSecurityPolicy]];google

  2.若是是原生的NSURLConnection,那么须要在NSURLConnectionDelegate的一个方法里面加代码,以下:加密

 1 - (void)connection:(NSURLConnection *)connection
 2 willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
 3 {
 4     NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
 5     //导入证书       NSLog(@"thePath===========%@",thePath);
 6     NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
 7     CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
 8     
 9     SecIdentityRef identity = NULL;
10     // extract the ideneity from the certificate
11     [self extractP12Data:inPKCS12Data toIdentity:&identity];
12     
13     SecCertificateRef certificate = NULL;
14     SecIdentityCopyCertificate (identity, &certificate);
15     
16     const void *certs[] = {certificate};
17     //                        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
18     // create a credential from the certificate and ideneity, then reply to the challenge with the credential
19     //NSLog(@"identity=========%@",identity);
20     NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent];
21     
22     //           credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
23     
24     [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
25 }          

  接下来是对NSURLSession的适配,如今公认更好的网络请求类,支持后台的数据下载和上传,并且自身是安全的。然而,在使用NSURLSession时须要在一个代理方法里配置ssl证书。以下:spa

 1 - (void)URLSession:(NSURLSession *)session
 2 didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 3  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
 4 {
 5     NSString *method = challenge.protectionSpace.authenticationMethod;
 6     if([method isEqualToString:NSURLAuthenticationMethodServerTrust]){
 7         NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
 8         completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
 9         return;
10     }
11     NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
12     NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
13     CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
14     SecIdentityRef identity;
15     // 读取p12证书中的内容
16     OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
17     if(result != errSecSuccess){
18     completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
19         return;
20     }
21     SecCertificateRef certificate = NULL;
22     SecIdentityCopyCertificate (identity, &certificate);
23     const void *certs[] = {certificate};
24     CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
25     NSURLCredential *credential1 = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
26     completionHandler(NSURLSessionAuthChallengeUseCredential, credential1);
27 }
 1 - (OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
 2     OSStatus securityError = errSecSuccess;
 3     CFStringRef password = CFSTR("clientepass");
 4     const void *keys[] = { kSecImportExportPassphrase };
 5     const void *values[] = { password };
 6     CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
 7     CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
 8     securityError = SecPKCS12Import(inP12Data, options, &items);
 9     if (securityError == 0) {
10         CFDictionaryRef ident = (CFDictionaryRef)CFArrayGetValueAtIndex(items,0);
11         const void *tempIdentity = NULL;
12         tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
13         *identity = (SecIdentityRef)tempIdentity;
14     }
15     if (options) {
16         CFRelease(options);
17     }
18     return securityError;
19 }

  其实适配https没有咱们想象的那么复杂,你找对了地方可能几分钟就弄好了,找不到,可能花几天。无论怎样,最后适配成功仍是要感谢网上的一些大神,虽然官网上面也有答案,但毕竟时间不等人,等我研究透彻,估计苹果又会有新的东西出来吧。至此,但愿能帮到正在为https适配而忧伤的小伙伴们。代理

相关文章
相关标签/搜索