苹果官方在2017年年初要求APP必须配置https(这里可以从喵神的博客了解),可是后来不知啥原因搁浅了,但这个东西终究还是要做的。不然随便一个抓包工具(charles等)随随便便就能抓到你所请求的数据,这些数据如果是明码的后果很严重(不是指明文),可以通过这些数据来判定服务端部署的数据接口,更能够嗅探到服务端的漏洞。而现在绝大部分APP使用的都是AFNetworking这个网络框架,我们就对AFNetworking如何配置https来做探讨。
服务器端如何实现https
这里就不在赘述https的原理了,网上有很多介绍的文章。https之所以安全是因为它采用了SSL/TLS协议的公钥加密法,其运行的基本流程是:
-
客户端向服务器端索要并验证公钥;
-
双方协商生成”对话密钥”;
-
双方采用”对话密钥”进行加密通信。
其中,第1和2步被称为握手阶段。握手阶段的细节这里就不赘述,我们只需要知道,通过握手阶段,客户端和服务器端主要交换了3个信息:
-
1,数字证书。该信息是我们进行开发需要关注的!数字证书包含了公钥等信息,一般由服务器发给客户端,接收方通过验证这个证书是不是由信赖的CA签发,或者与本地的证书相对比,来判断证书是否可信;假如需要双向验证,则服务器和客户端都需要发送数字证书给对方验证;
-
2,3个随机数。3个随机数是用于生成对话密钥的,我们不需要关心这细节;
-
3,加密通信协议。客户端和服务器端通信需要采取同样的加密通信协议,我们也不需要太关注。
所以咱们需要做的就是拿到数字证书数字证书及CA,这里有两种方式:
-
向官方CA认证机构申请证书
-
自建证书,配置给服务器
第一种方法是最优的,建立网站的话,直接就会被信任。而服务器作为移动端app的服务器时,也不需要为ATS做过多的适配(正是我所需要积累知识的方向)。虽然说权威的机构认证都是需要钱的,但是如今也不乏存在免费的第三方认证机构。
第二种方法虽然对于app和服务器间的通讯是可行的,但是如果从网站打开链接时会弹出一个警告提醒,提醒这是一个不受信任的网站,需要用户手动设置信任才行,这种体验会让用户感觉网站不安全。而客户端配置时需要将info.plist文件中将App Transport Security Settings中的Allow Arbitrary Loads设置为YES或者在App Transport Security Settings下添加白名单(新增Exception Domains选项,将自己服务器的域名放进去),这里我要说的是许多人不管三七二十一是直接将Allow Arbitrary Loads设置为YES,这种设置会信任其他所有的http请求,相当于https白做了,所以后者才是可取的。
这里有一个方法可以快速检测服务器的https特性是否符合ATS的要求: 控制台输入
nscurl --ats-diagnostics --verbose https://example.com
这个https://example.com
就是你想检测的域名,咱们来试试知乎
nscurl --ats-diagnostics --verbose https://www.zhihu.com
输出如下:
Starting ATS Diagnostics
Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://www.zhihu.com.
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
================================================================================
Default ATS Secure Connection
---
ATS Default Connection
ATS Dictionary:
{
}
Result : PASS
---
================================================================================
Allowing Arbitrary Loads
---
Allow All Loads
ATS Dictionary:
{
NSAllowsArbitraryLoads = true;
}
Result : PASS
---
================================================================================
Configuring TLS exceptions for www.zhihu.com
---
TLSv1.2
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.2";
};
};
}
Result : PASS
---
---
TLSv1.1
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.1";
};
};
}
Result : PASS
---
---
TLSv1.0
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.0";
};
};
}
Result : PASS
---
================================================================================
Configuring PFS exceptions for www.zhihu.com
---
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring PFS exceptions and allowing insecure HTTP for www.zhihu.com
---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled for www.zhihu.com
---
TLSv1.2 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.2";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.1 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.1";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.0 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.0";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for www.zhihu.com
---
TLSv1.2 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.2";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.1 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.1";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"www.zhihu.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.0";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
可以看到知乎在所有测试中的结果都是PASS,知乎对用户的信息安全保护工作做得还是不错的,赞!自己的服务器配置好了https后也可以用这个来进行尝试。
iOS端如何实现https
基于对HTTPS运行机制的理解,我们知道,在iOS客户端实现与服务器的https通信,前提条件是你的服务器是一个提供了https的服务器。如果前提得以满足,那么iOS客户端就需要向服务器发出请求索要公钥,而后验证公钥,然后进行握手,最后开始加密通信。那么,具体怎么做呢?难倒这些都需要我自己实现吗?肯定不是的,这种基础性工作,苹果早就做好了,著名的第三方库AFNetworking也早就做好了。
1.删除掉info.plist文件中App Transport Security Settings及其子项Allow Arbitrary Loads,让ATS恢复到默认状态。
2.修改主域名为项目的https域名
由此可知,对于符合ATS要求的HTTPS服务器,在iOS端不需要对ATS做特殊的适配就能和HTTPS服务器进行通信。而要符合ATS要求,则需要老老实实地创建证书请求,然后到权威机构认证,随之配置到服务器。是不是超级简单?
对于自建证书的方法和配置下篇文章再讲。