iOS 用自签名证书实现 HTTPS 请求的原理实例讲解
在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求。默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info.plist中添加NSAllowsArbitraryLoads设置绕过ATS(App Transport Security)的限制(否则须在应用审核时进行说明并很可能会被拒)。所以还未进行相应配置的公司需要尽快将升级为HTTPS的事项提上进程了。
本文将简述HTTPS及配置数字证书的原理并以配置实例和出现的问题进行说明,希望能对你提供帮助。(比心~)
HTTPS:
简单来说,HTTPS就是HTTP协议上再加一层加密处理的SSL协议,即HTTP安全版。相比HTTP,HTTPS可以保证内容在传输过程中不会被第三方查看、及时发现被第三方篡改的传输内容、防止身份冒充,从而更有效的保证网络数据的安全。
HTTPS客户端与服务器交互过程:
1、 客户端第一次请求时,服务器会返回一个包含公钥的数字证书给客户端;
2、 客户端生成对称加密密钥并用其得到的公钥对其加密后返回给服务器;
3、 服务器使用自己私钥对收到的加密数据解密,得到对称加密密钥并保存;
4、 然后双方通过对称加密的数据进行传输。
数字证书:
在HTTPS客户端与服务器第一次交互时,服务端返回给客户端的数字证书是让客户端验证这个数字证书是不是服务端的,证书所有者是不是该服务器,确保数据由正确的服务端发来,没有被第三方篡改。数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方身份。证书由公钥、证书主题(Subject)、数字签名(digital signature)等内容组成。其中数字签名就是证书的防伪标签,目前使用最广泛的SHA-RSA加密。
证书一般分为两种:
一种是向权威认证机构购买的证书,服务端使用该种证书时,因为苹果系统内置了其受信任的签名根证书,所以客户端不需额外的配置。为了证书安全,在证书发布机构公布证书时,证书的指纹算法都会加密后再和证书放到一起公布以防止他人伪造数字证书。而证书机构使用自己的私钥对其指纹算法加密,可以用内置在操作系统里的机构签名根证书来解密,以此保证证书的安全。
另一种是自己制作的证书,即自签名证书。好处是不需要花钱购买,但使用这种证书是不会受信任的,所以需要我们在代码中将该证书配置为信任证书。这就是本文的主要目的。
具体实现
我们在使用自签名证书来实现HTTPS请求时,因为不像机构颁发的证书一样其签名根证书在系统中已经内置了,所以我们需要在App中内置自己服务器的签名根证书来验证数字证书。
首先将服务端生成的.cer格式的根证书添加到项目中,注意在添加证书要一定要记得勾选要添加的targets。这里有个地方要注意:苹果的ATS要求服务端必须支持TLS 1.2或以上版本;必须使用支持前向保密的密码;证书必须使用SHA-256或者更好的签名hash算法来签名,如果证书无效,则会导致连接失败。由于我在生成的根证书时签名hash算法低于其要求,在配置完请求时一直报NSURLErrorServerCertificateUntrusted = -1202错误,希望大家可以注意到这一点。
本文使用AFNetworking 3.0来配置证书校验。其中AFSecurityPolicy类中封装了证书校验的过程。
AFSecurityPolicy分三种验证模式:
1、AFSSLPinningModeNone:只验证证书是否在新人列表中
2、AFSSLPinningModeCertificate:验证证书是否在信任列表中,然后再对比服务端证书和客户端证书是否一致
3、 AFSSLPinningModePublicKey:只验证服务端与客户端证书的公钥是否一致
这里我们选第二种模式,并且对AFSecurityPolicy的allowInvalidCertificates和 validatesDomainName进行设置。
AFSecurityPolicy具体配置代码如下:
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
securityPolicy.allowInvalidCertificates = YES; //是否允许使用自签名证书
securityPolicy.validatesDomainName = NO; //是否需要验证域名
self.manager = [AFHTTPSessionManager manager];
self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
self.manager.securityPolicy = securityPolicy;
服务端在接收到客户端请求时会有的情况需要验证客户端证书,要求客户端提供合适的证书,再决定是否返回数据。这种情况即为质询(challenge)认证,双方进行公钥和私钥的验证。
为实现客户端验证,manager须设置需要身份验证回调的方法:
- (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block
并实现具体代码来替换AFNetworking的默认实现。其中参数challenge为身份验证质询,block返回对身份验证请求质询的配置。
在接受到质询后,客户端要根据服务端传来的challenge来生成所需的NSURLSessionAuthChallengeDisposition disposition和NSURLCredential *credential。disposition指定应对这个质询的方法,而credential是客户端生成的质询证书,注意只有challenge中认证方法为NSURLAuthenticationMethodServerTrust的时候,才需要生成挑战证书。最后回应服务器的质询。
具体实现代码如下:
[self.manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *_credential) {
// 获取服务器的trust object
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
//导入自签名证书
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"cer"];
NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
NSArray *cerArray = @[caCert];
weakSelf.manager.securityPolicy.pinnedCertificates = cerArray;
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
NSCAssert(caRef != nil, @"caRef is nil");
NSArray *caArray = @[(__bridge id)(caRef)];
NSCAssert(caArray != nil, @"caArray is nil");
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
//选择质询认证的处理方式
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__autoreleasing NSURLCredential *credential = nil;
//NSURLAuthenticationMethodServerTrust质询认证方式
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//基于客户端的安全策略来决定是否信任该服务器,不信任则不响应质询 。
if ([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
//创建质询证书
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
//确认质询方式
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
//取消质询
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
return disposition;
}];
详细代码发布在了github上,使用时请注意在ViewController和NetworkManager中#Warning的提示,将证书拖入项目并在NetworkManager中添加证书名称,在ViewController添加自己的URL。
文章中如有错误和疏漏,欢迎留言指教讨论。
参考文章:
Certificate, Key, and Trust Services Tasks for iOS
http://t.cn/RIieZFE
关于 iOS 10 中 ATS 的问题
http://t.cn/R5SFNd2
App Transport Security(ATS)
http://southpeak.github.io/2015/09/14/app-transport-security-ats/
数字证书原理
http://www.cnblogs.com/JeffreySun/archive/2010/06/24/1627247.html
iOS使用自签名证书实现HTTPS请求
http://www.jianshu.com/p/e6a26ecd84aa
相关文章:

WordPress Editorial Calendar插件权限安全绕过漏洞
漏洞名称:WordPress Editorial Calendar插件权限安全绕过漏洞CNNVD编号:CNNVD-201302-369发布时间:2013-02-22更新时间:2013-02-22危害等级: 漏洞类型:权限许可和访问控制威胁类型:远程CVE编号…

文件操作(ifstream、ofstream、fstream)
原文链接:http://blog.csdn.net/soar_ersa/article/details/3908943 转载于:https://www.cnblogs.com/MrYuan/p/5288264.html
linux error log 换行,日志提示
日志提示线上问题,需要看日志。控制台可以打印Mybatis操作的SQL语句。开发流程:第一步:加入依赖image.png第二步:在项目的resources中加入log4j属性文件image.png第三步:演示image.png扩展了解一、日志概念的介绍Log4j…

本页面添加至收藏夹
经常在网站页面上需要把本页面添加至收藏夹 <script type"text/javascript">function addMe() {var url document.location.href;var wTitle document.title;if (document.all) {window.external.addFavorite(url, wTitle);} else if (window.sidebar) {wind…

javascript——Array类型
今天这节教程不仅仅是阐述ECMAScript3的部分功能,同时也会阐述有关EXMASctip5的很多新的功能。 一、创建 因为它是一个引用类型,自然就需要在使用前先构造它。 我将分成两种方式来讲述 I、构造函数 1.空的Array实例 var colors new Array(); 2.初始化存…

iOS使用自签名证书实现HTTPS请求
原文链接:http://www.jianshu.com/p/e6a26ecd84aa 由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS中使用HTTPS请求的实现。相信大家对HTTPS都或多或少有些了解,这里我就不再介…

蜜蜂实训平台c语言考试答案,北理c语言上机答案(全)
小蜜蜂的不过,麻烦大家上百度找一下~1 Hello world让我们用C语言向世界问好。 最早的程序基本是这个样子的: 程序一:#include void main() {printf("Hello world.\n"); }程序二:#include int main() {printf("Hello world.\n&…

ecshop目录结构
ECShop 最新程序 的结构图及各文件相应功能介绍ECShop文件结构目录┣ activity.php 活动列表┣ affiche.php 广告处理文件┣ affiliate.php 生成商品列表┣ article.php 文章内容┣ article_cat.php文章分类┣ auction.php 拍卖前台文件┣ brand.php 品牌列表┣ captcha.php 生…
一劳永逸,iOS 网页视图控制器通用类封装
原文链接:http://www.jianshu.com/p/553424763585随着 H5 的发展,在 iOS 开发中,网页视图的使用率逐渐提升,为了增加代码封装度、减轻开发负担,因此通常会对网页视图进行通用类的封装,本文简单讲述网页视图…

enyo官方开发入门教程翻译一Layout之Fittables
Fittables Fittable包帮助你创建布局更合理的使用可用空间(app都有这样的布局需求,但使用以前的web技术很难做到这一点)。个人观点,现在移动Web开发框架中有很多都支持自适应布局,如senchatouch,但是enyo的…

c语言 栈结构存放数据类型,数据结构——栈的详解
栈和队列是两种重要的线性结构,从数据结构的角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表的子集。他们是操作受限的线性表,因此,可称为限定性的数据结构。但从数据类型角度看,他们是…

Verlet Integration
Verlet Integration Verlet 积分法是一种用于求解牛顿运动方程的数值方法,被广泛运用于动力学模拟以及视频游戏中。尔莱算法的优点在于:数值稳定性比简单的欧拉方法高很多,并保持了物理系统中的时间可逆性与相空间体积元体积守恒的性质。 基本…

[译] iOS 开发之新版 APNs 搭建必备知识
原文链接:http://www.jianshu.com/p/d8dba6c2c07a本文的大部分内容是对苹果关于 APNs 官方文档的翻译以及整理。 —— 由 稀土君 分享本文的大部分内容是对苹果关于APNs官方文档的翻译以及整理。 一、设备token和消息的生命周期 关于设备token以及推送消息的生命周期…

使用Application.GetResourceStream从XAP安装包加载任意资源
不得不说,WP7开发的资料真的是太少了,国内有句话叫“天下文章一大抄”,查Application.GetResourceStream的用法,找遍了整个网络,无非就那一两篇,而且写得还不完整,包括微软官方的例子。在花了近…

c语言知道算法写不出代码,这个代码怎么写算法啊,求教,我真的不会写算法怎么办#incl...
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼这个代码怎么写算法啊,求教,我真的不会写算法怎么办#include "stdio.h"#define N 3 //学生数3。struct Student //建立结构体。{int num;char name[20];float score[3];float aver;};int main(){v…

猎豹MFC--列表控件ListControl
ListControl添加变量:关联控件变量:初始化:设置样式 添加列标题:添加位图资源:添加位图变量:创建图像列表:并把图像列表 给 列表控件使用:双击添加行按钮:添加第2列时 不…
iOS 命令行自动打包 (archive)
原文链接:http://www.jianshu.com/p/2247f76404ebiOS 开发工程师在测试修复 bug 的过程中,一般会存在频繁打包的情况,如果一步步在 xcode 中点击 archive,下一步,下一步。。。这样太浪费我们的时间了。下面我们来介绍在…

看看现在大型网站都是用什么语言写的 ?
看看现在大型网站都是用什么语言写的 ? 不排除一个网站用多种技术!如淘宝是Java php,底层是java,表现层是php。新浪,网易,腾讯应该也是用了多种技术。 据说是这样的:php,新浪&#…

数据结构 算法与应用C 语言描述第六章,数据结构算法与应用-C语言描述002.pdf
下载下载第2 章 程 序 性 能以下是本章中所介绍的有关程序性能分析与测量的概念:• 确定一个程序对内存及时间的需求。• 使用操作数和执行步数来测量一个程序的时间需求。• 采用渐进符号描述复杂性,如 O、 、 、o 。• 利用计时函数测量一个程序的实际…
GCD 容易让人迷惑的几个小问题
来源:涂耀辉 链接:http://www.jianshu.com/p/ff444d664e51 写在开头: 本文旨在阐述一些大家容易产生迷惑的GCD相关内容,如果是需要了解一些GCD概念或者基础用法,可以看看这两篇文章:GCD 扫盲篇、巧谈GCD 。…

【贪心】【codevs】1214 线段覆盖
http://codevs.cn/problem/1214/ 我去这个题。。。wa的我都没脾气了。。。 我写while(~scanf(“%d”, &n))竟然是不对的。。。 这个程序你妹多次输入是不能结束的????…

虚函数表剖析,网上转的,呵呵
http://www.cppblog.com/xczhang/archive/2008/01/20/41508.html C虚函数表解析(转)C中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的…

c++语言文件流,C++ IO类、文件输入输出、string流详细讲解
新的C标准中有三分之二的内容都是描述标准库。接下来重点学习其中几种核心库设施,这些是应该熟练掌握的。标准库的核心是很多容器类(顺序容器和关联容器等)和一簇泛型算法(该类算法通常在顺序容器一定范围内的元素上或其他类型的序列上进行操作)。该篇主要学习IO库。…
iOS 走近商城 APP(三 WKWebView 商品规格选择框架封装)
原文链接:http://www.jianshu.com/p/293ee1bfe104商城 —— 由 3033 分享开篇 忽然发现最近也只有值班才能写东西了,中间更新了两篇其他的断了下商城相关的文章,仔细看了看之前觉得干货太少,今天写点实际的吧,闲说少说…

c语言如何不产生僵尸进程,第三章 九析带你处理 zombie(defunct) 进程
目录1 前言2 僵尸进程2.1 进程简介2.2 僵尸进程例子2.3 僵尸进程危害3 处理僵尸进程3.1 kill 命令3.2 kill 父进程3.3 reboot3.4 magic sysrq key 方法1 前言在 centos7 跑 Docker 和 k8s 时,偶尔会出现 systemctl 失效的情况,现象如下:Faile…

音视频开发学习笔记
http://www.jianshu.com/notebooks/6409162/top

VS2010 MFC中改变static字体颜色、大小、背景颜色(自定义类),及手动关联变量的方法...
在MFC的Dialog工程中生成一个CStatic的自定义类,类名例如为:CColorStatic 定义必要的变量: protected:COLORREF m_crText; // 字体颜色COLORREF m_crBackColor; // 背景颜色HBRUSH m_hBrush; // 画刷LOGFONT m_lf; // 字体…

android 上传字符串,Android中发送Http请求(包括文件上传、servlet接收)的实例代码...
/*** 通过拼接的方式构造请求内容,实现参数传输以及文件传输* param actionUrl* param params* param files* return* throws IOException*/public static String post(String actionUrl, Map params,Map files) throws IOException {String BOUNDARY java.util.UU…

JavaScript最全编码规范
转载: JavaScript最全编码规范 类型 ●基本类型:访问基本类型时,应该直接操作类型值 ●string ●number ●boolean ●null ●undefined var foo 1; var bar foo; bar 9; console.log(foo, bar); // > 1, 9 ●复合类型:访问复合类型时&a…
源码推荐:collectionView拖拽,仿凤凰FM iOS 局部监听键盘再也不会挡住输入框
UICollectionView拖拽移动单元以及本地保存(上传者:dengqi) UICollectionView拖拽移动单元以及本地保存,可以保存你上次移动的位置。 仿映客直播导航条(上传者:Coolcool) 仿映客直播自定义TabBa…