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

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

  1.如果使用AF进行网络数据请求,那么使用如下方法即可:

 - (AFSecurityPolicy*)customSecurityPolicy

 {
//先导入证书
//在这加证书,一般情况适用于单项认证
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ailian" ofType:@"cer"];//证书的路径 NSData *certData = [NSData dataWithContentsOfFile:cerPath];
if (certData==nil) {
return nil;
}
// AFSSLPinningModeCertificate 使用证书验证模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO // 如果是需要验证自建证书,需要设置为YES securityPolicy.allowInvalidCertificates = YES; //validatesDomainName 是否需要验证域名,默认为YES; //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。 //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。 //如置为NO,建议自己添加对应域名的校验逻辑。 securityPolicy.validatesDomainName = NO; securityPolicy.pinnedCertificates = @[certData]; return securityPolicy; }

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

  然后加上下面的代码:

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

[_manager setSecurityPolicy:[self customSecurityPolicy]];

  2.如果是原生的NSURLConnection,那么需要在NSURLConnectionDelegate的一个方法里面加代码,如下:

 - (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
//导入证书 NSLog(@"thePath===========%@",thePath);
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; SecIdentityRef identity = NULL;
// extract the ideneity from the certificate
[self extractP12Data:inPKCS12Data toIdentity:&identity]; SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate); const void *certs[] = {certificate};
// CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
// create a credential from the certificate and ideneity, then reply to the challenge with the credential
//NSLog(@"identity=========%@",identity);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent]; // credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent]; [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}

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

 - (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
NSString *method = challenge.protectionSpace.authenticationMethod;
if([method isEqualToString:NSURLAuthenticationMethodServerTrust]){
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
return;
}
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
SecIdentityRef identity;
// 读取p12证书中的内容
OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
if(result != errSecSuccess){
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
return;
}
SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate);
const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, , NULL);
NSURLCredential *credential1 = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential1);
}
 - (OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("clientepass");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, , NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, , , NULL);
securityError = SecPKCS12Import(inP12Data, options, &items);
if (securityError == ) {
CFDictionaryRef ident = (CFDictionaryRef)CFArrayGetValueAtIndex(items,);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
}
if (options) {
CFRelease(options);
}
return securityError;
}

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

iOS适配https详解的更多相关文章

  1. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  2. iOS开发者证书-详解

    iOS开发者证书-详解/生成/使用 本文假设你已经有一些基本的Xcode开发经验, 并注册了iOS开发者账号. 相关基础 加密算法 现代密码学中, 主要有两种加密算法: 对称密钥加密 和 公开密钥加密 ...

  3. 基于rem的移动端响应式适配方案(详解) 移动端H5页面的设计稿尺寸大小规范

    基于rem的移动端响应式适配方案(详解) : https://www.jb51.net/article/118067.htm 移动端H5页面的设计稿尺寸大小规范 http://www.tuyiyi.c ...

  4. 公钥与私钥,HTTPS详解

    1.公钥与私钥原理1)鲍勃有两把钥匙,一把是公钥,另一把是私钥2)鲍勃把公钥送给他的朋友们----帕蒂.道格.苏珊----每人一把.3)苏珊要给鲍勃写一封保密的信.她写完后用鲍勃的公钥加密,就可以达到 ...

  5. 转载]IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本 )

    原文地址:IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本作者:佐佐木小次郎 因为最近项目上要用有关LBS的功能.于是我便做一下预研. 一般说来LBS功能一般分为两块:一块是地理 ...

  6. iOS中-Qutarz2D详解及使用

    在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...

  7. iOS 2D绘图详解(Quartz 2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)

    前言:一个路径可以包含由一个或者多个shape以及子路径subpath,quartz提供了很多方便的shape可以直接调用.例如:point,line,Arc(圆弧),Curves(曲线),Ellip ...

  8. iOS开发——Block详解

    iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...

  9. iOS开发:详解Objective-C runTime

    Objective-C总Runtime的那点事儿(一)消息机制 最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎 ...

随机推荐

  1. C语言初学者代码中的常见错误与瑕疵(23)

    见:C语言初学者代码中的常见错误与瑕疵(23)

  2. DELPHI XE5 与SQLITE

    最近一次使用DELPHI做项目是使用DELPHI2009,为了访问本地数据库方便,使用ACCESS数据库,不需要安装驱动,(WINDOWS自带),但是ACCESS数据库的性能确实很糟糕,通过ADO连接 ...

  3. spring @condition 注解

    spring @condition注解是用来在不同条件下注入不同实现的 demo如下: package com.foreveross.service.weixin.test.condition; im ...

  4. uboot命令

    uboot是怎么启动kernel的呢? 先熟悉一下uboot的命令吧. 首先是md, 查看内存. OpenJTAG> md 000000000: ea000014 e59ff014 e59ff0 ...

  5. 搭建基于Jenkins salt-api的运维工具

    1. 安装salt-master和salt-minion 安装过程不再赘述,请参考http://docs.saltstack.com/en/latest/topics/installation/ind ...

  6. Dynamics AX 2012 R2 业务系列-销售业务流程

    在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 1.销售的主要职责 其实这里说的职责主要是针对销售文员,并非整天外面满世界跑业 ...

  7. UITableView heightForHeaderInSection遇到的坑

    出现这种现象只需要把 heightforfoot改为0.01 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSectio ...

  8. C#利用反射机制创建对象

    "反射"其实就是利用程序集的元数据信息. 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间. 1.假设你要反射一个 DLL 中的类,并且没有引用 ...

  9. java反射类内容获取

    private void DtoReflect(Object obj, MqDto mqDto) throws Exception { Map map = getMap(mqDto); if(obj= ...

  10. WEB前端html基础中的各类标签介绍

    2:html中有很多标签,这里列举十几种标签,有它们的用法及在使用过程中的注意事项!