iOS适配https详解
马上就要元旦了,网上流传元旦之后苹果会对所有的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详解的更多相关文章
- 了解iOS消息推送一文就够:史上最全iOS Push技术详解
本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...
- iOS开发者证书-详解
iOS开发者证书-详解/生成/使用 本文假设你已经有一些基本的Xcode开发经验, 并注册了iOS开发者账号. 相关基础 加密算法 现代密码学中, 主要有两种加密算法: 对称密钥加密 和 公开密钥加密 ...
- 基于rem的移动端响应式适配方案(详解) 移动端H5页面的设计稿尺寸大小规范
基于rem的移动端响应式适配方案(详解) : https://www.jb51.net/article/118067.htm 移动端H5页面的设计稿尺寸大小规范 http://www.tuyiyi.c ...
- 公钥与私钥,HTTPS详解
1.公钥与私钥原理1)鲍勃有两把钥匙,一把是公钥,另一把是私钥2)鲍勃把公钥送给他的朋友们----帕蒂.道格.苏珊----每人一把.3)苏珊要给鲍勃写一封保密的信.她写完后用鲍勃的公钥加密,就可以达到 ...
- 转载]IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本 )
原文地址:IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本作者:佐佐木小次郎 因为最近项目上要用有关LBS的功能.于是我便做一下预研. 一般说来LBS功能一般分为两块:一块是地理 ...
- iOS中-Qutarz2D详解及使用
在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...
- iOS 2D绘图详解(Quartz 2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)
前言:一个路径可以包含由一个或者多个shape以及子路径subpath,quartz提供了很多方便的shape可以直接调用.例如:point,line,Arc(圆弧),Curves(曲线),Ellip ...
- iOS开发——Block详解
iOS开发--Block详解 1. Block是什么 代码块 匿名函数 闭包--能够读取其他函数内部变量的函数 函数变量 实现基于指针和函数指针 实现回调的机制 Block是一个非常有特色的语法,它可 ...
- iOS开发:详解Objective-C runTime
Objective-C总Runtime的那点事儿(一)消息机制 最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎 ...
随机推荐
- 二十八、Java基础--------正则表达式
在对字符串进行处理时一方面可以利用String对象的一些处理方法另一方面可以利用正则表达式,但是一般情况下用String对象方法进行处理起来会相对麻烦一些而正则表达式可以很方便的解决问题.为了更好的学 ...
- qt qml ajax 获取 json 天气数据示例
依赖ajax.js类库,以下代码很简单的实现了获取天气json数据并展示的任务 [TestAjax.qml] import QtQuick 2.0 import "ajax.js" ...
- 最常用的截取函数有left,right,substring
最常用的截取函数有left,right,substring 1.LEFT ( character_expression , integer_expression ) 返回从字符串左边开始指定个数的字符 ...
- Core Data 使用映射模型
Core Data 使用映射模型 如果新版本的模型存在较复杂的更改,可以创建一个映射模型,通过该模型指定源模型如何映射到目标模型. 创建映射模型,新建File, Core Data 选择Mappin ...
- Linux的fasync驱动异步通知详解【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51851338 版权声明:本文为博主原创文章,未经博主允许不得转载. 工作项目用有 ...
- linux中oops信息的调试及栈回溯【转】
本文转载自:http://blog.csdn.net/kangear/article/details/8217329 ========================================= ...
- 从svn资源库目录checkout出maven项目方法
从svn资源库目录checkout出maven项目方法,如下图所示:
- Java设计模式(二)——迭代模式
迭代模式的基本定义:对于一组对象集合(数组.堆栈.列表或散列),用户无需关心它的底层实现而能够通过调用统一接口遍历当中的所有元素.由于jdk已经对常见的迭代模式实现了封装,本文直接提供Collecti ...
- Base:-用数组赋值实现while和shift功能
3列数组,arrayA,arrayB,arrayC:分别一一对应主机及其主机所能创建的资源数,还有arrayC表示需要创建的资源数:arrayA=("192.168.1.1" &q ...
- 【GO】GO语言学习笔记三
7.数组: 几乎是最常用的数据类型了... 数组就是指一系列同一类型数据 的集合.数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数 组的长度. 常规的数组声明方法: ...