前言
一开始项目中使用的是HTTP请求,在info.plist中配置了ATS用以使用,过了一阵后台将线上改成了HTTPS
但素!
真机联调的时候,AFN网络请求总是失败,报错信息为
Error Domain=NSURLErrorDomain Code=-1007 "too many HTTP redirects"
网上查原因说是后台问题,沟通尝试了好久,用下列代码验证了后台HTTPS是符合苹果要求的
nscurl --ats-diagnostics --verbose 加服务器地址
那就是我的问题喽~
最终:
重启Xcode,clean项目,发现再次运行时,模拟器OK
真机依然不OK
断点测试,模拟器网络请求就是成功,真机就是失败!
然后,删掉了真机中原来项目,重新clean运行OK
一头雾水,到现在也不知为何真机运行,都加了断点跟代码,怎么会...
若有大神看见望能指点一二
因此Bug,花心思对HTTPS研究了一下,现用简单易懂的方式记录一下~
HTTP和HTTPS的区别
-
HTTP
介绍: 超文本传输协议,是用于从万维网(www)服务器传输超文本到本地浏览器的传输协议
1.端口80
2.以明文方式发送内容,不提供任何方式的数据加密
3.连接方式:无状态连接
-
HTTPS
介绍: 是HTTP的安全版,在HTTP下加入SSL层(安全层)
1.端口443
2.SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密
3.连接方式:SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议
4.需要CA证书
-
备注
iOS9之后,苹果新特性要求App内访问的网络必须使用HTTPS协议,提高数据传输之间的安全性.并且有如下要求:
1.传输层协议(TLS)至少为1.2版本
2.连接的加密方式要提供Forward Secrecy,支持如下加密算法
3.证书至少要使用一个SHA256的指纹与任一个2048位或者更高位的RSA密钥,或者是256位或者更高位的ECC密钥。如果不符合其中一项,请求将被中断并返回nil.
如果项目使用的是http协议,怎么办呢
因为苹果是用ATS(App Transport Security)(一项隐私保护功能)来屏蔽HTTP明文传输协议资源加载,我们将它禁掉,就可以暂且使用HTTP啦
如何禁用:
在info.plist中添加键值对
App Transport Security Settings
Allow Arbitrary Loads
上面介绍的方法虽然解决了网络访问的问题,但是苹果提供的安全保障也被关闭了。
需要注意的是:不要以为后台是http我们也能访问到(因为info.plist里添加了键值对),但是即时添加了键值对,WebView有的情况下是访问不了http的,最好还是改成https的
不过,对于H5,网页浏览和视频播放的行为,iOS 10 中新加入了NSAllowsArbitraryLoadsInWebContent 键。通过将它设置为 YES , 可以让你的 app 中的 WKWebView 和使用 AVFoundation 播放的在线视频不受 ATS 的限制,但是10以前都不行哦~
另外:
因为目前苹果允许开发者暂时关闭ATS,可以继续使用HTTP连接,但说到2017年1月1日 ,App Store中的所有应用都必须启用ATS安全功能,延期了...
SSL/TLS协议
互联网中,如果赤裸裸的通讯发送,没有安全性可言
为了安全,设计出了SSL/TLS协议
1.所有信息都是加密传播,第三方无法窃听。
2.具有校验机制,一旦被篡改,通信双方会立刻发现
3.配备身份证书,防止身份被冒充
SSL/TLS协议基本思路
互联网的通信安全,建立在SSL/TLS协议之上
思路就是:公钥加密法,请看下图:
翻译成文字就是:
(1) 客户端向服务器端索要并验证公钥。
(2) 双方协商生成"对话密钥"。
(3) 双方采用"对话密钥"进行加密通信。
平时老说的握手阶段,就是上面的前两步
那么握手协议怎么实现呢
- 客户端先向服务器发出加密通信的请求
包含以下:
1.支持的协议版本,比如TLS 1.0版
2.一个客户端生成的随机数,稍后用于生成"对话密钥"
3.支持的加密方法,比如RSA公钥加密
4.支持的压缩方法
- 服务器回应(一台服务器有一个数字证书)
1.确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
2.生成一个随机数,稍后用于生成"对话密钥"
3.确认使用的加密方法,比如RSA公钥加密
4.服务器证书
- 客户端再次回应(前提是服务器的证书是可靠安全的)
1.一个随机数。该随机数用服务器公钥加密,防止被窃听
2.编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
3.客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
- 服务器根据随机数,生成本次会话所用的"会话密钥",最后回应
1.编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
2.务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容
说了这么多,很高大上的样子,和我有什么关系呢~
关系就是:HTTPS = HTTP + SSL/TLS协议
关于HTTPS,服务器做了什么
关于服务器这部分,简单介绍一下
我们都知道,HTTP请求原理是
HTTPS的请求原理,再贴一遍这个图:
看图知道,服务器需要:
1.申请CA(证书认证机构)证书,申请后就有了公钥和私钥
2.将证书配置到服务器
搭建完,怎么确认你建的这个HTTPS是符合苹果的ATS的呢
服务器人员可以让你的iOS开发小伙伴,在终端中输入:
nscurl --ats-diagnostics --verbose 加服务器地址
若出现的都是PASS,证明你是OK的
关于HTTPS,iOS需要做什么
好了,HTTPS的服务器服务器也建好了,现在我们可以进行HTTPS通信了
现在iOS客户端应该
1.向服务器发出请求索要公钥,而后验证公钥
2.进行握手
3.最后加密通信
???一头雾水.......
别害怕,这种基础性工作,苹果已经为我们做好了,AFN也做好了,那我们还需要做什么?
使用了AFN网络请求,我们还需要做的是
1.以前和后台传输数据,会定义N种叠加的加密规则,我认为HTTPS已经足够机密,所以,省去加密了
2.info.plist中的禁用ATS,可以去掉了
3.将url修改为HTTPS服务器的url
以上的前提是,服务器端HTTPS是符合ATS特性要求的
AFN替我们做了什么
这里其实还不了解,后面详细研究一下再整理出来
NSURLConnection 已经封装了https连接的建立、数据的加密解密功能,我们直接使用NSURLConnection是可以访问 https网站的,但NSURLConnection并没有验证证书是否合法,无法避免中间人攻击。要做到真正安全通讯,需要我们手动去验证服务端返回的 证书
而AFN中,AFSecurityPolicy封装了证书验证的过程
1.指定https为默认的认证方式
2.AFN验证服务端的证书,其实苹果系统底层也会帮我们验证
等等等等
这里需要重点备注一下:
服务器申请的证书,若是正规付费的,那么OK,直接按照我上面说的做就行了
但如果是申请的有些免费的,不是可信赖的,那么,就稍微麻烦点了
下面讲一下怎么判断是否正规
1.在Safari中输入你们的Https地址
2.看前面有没有安全锁
请看正规的,例如百度,有安全锁:
请看不正规的,例如12306,没有锁
点击购票会提示:
因为我们公司是付费的,安全,所以我没有试过不安全的情况
若不安全,请参考下面文章做相应处理
http://www.jianshu.com/p/75d96b72bfb1
其他相关知识
网络协议是什么鬼
SSL/TLS协议是类似于MD5的加密协议
HTTP协议是基于TCP/IP的协议,大多数协议都是基于TCP/IP的
和后台数据传输时,其实底层,会先验证我们之间的协议
协议都是: 协议头(前八位) + 数据 + 大小
我们也可以基于TCP/IP定一个自己的协议
比如叫DQQ协议,指定的规则假如为(数据转成int型)*2/3-18
那么,我们发给后台就是 (DQQ头) + 数据 + 假如是14K
后台收到后,先判断是不是正常的协议格式(检查是否是头+数据+大小)
然后验证前八位,发现是DQQ
那么就按照我定的规则来解析
那么,我们说的公钥,证书三次握手等,后台是在哪里验证的呢
我们后台时PHP,线上布置在阿里云服务器上,那么,流程如下图
客户端数据发送到阿里云,其实是先发到nginx服务器
nginx服务器会先放到它的队列中
然后并发的发给PHP服务器
返回时同理
重点是:
公钥,证书三次握手等,nginx服务器帮后台做好了
至于我们iOS,苹果也帮我们做好了
那么JSON呢
以前一直以为是为了统一数据格式,所以和后台的传输格式用的是JSON
然而
你就算是传自己的语言也是可以传输的,后台接到后,按照一定规则转换也是一样的
那么,为什么不用自己的语言传输呢
原因1: 数据体积大
原因2: 传输慢
JSON是目前比较通用的一种传输数据格式,你可以理解为数据转换成它体积又小速度又快
但素现在也有了更好的选择,那就是PB,体积是JSON的1/14
假如"hello word",用JSON传输需要14K的话
用PB只需要1K
酷爆了,有关PB下次写一篇文章单独讲,这里就不多赘述了