写在前面的话
在iOS9之前公司就用了HTTPS,iOS9苹果把所有的HTTP请求都改为HTTPS了,HTTPS也变成了趋势。iOS9系统发送的网络请求将统一使用TLS 1.2 SSL。采用TLS 1.2 协议,目的是 强制增强数据访问安全,而且系统 Foundation 框架下的相关网络请求,将不再默认使用 Http 等不安全的网络协议,而默认采用 TLS 1.2。
Apple让你的HTTP采用SSL/TLS协议,就是让你从HTTP转到HTTPS。
不使用SSL/TLS的HTTP通信,就是不加密的通信!
所有信息明文传播,带来了三大风险:
- 窃听风险(eavesdropping):第三方可以获知通信内容。
- 篡改风险(tampering):第三方可以修改通信内容。
- 冒充风险(pretending):第三方可以冒充他人身份参与通信。
SSL/TLS协议是为了解决这三大风险而设计的,希望达到:
- 所有信息都是加密传播,第三方无法窃听。
- 具有校验机制,一旦被篡改,通信双方会立刻发现。
- 配备身份证书,防止身份被冒充。
https原理
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。客户端和服务端建立一个连接,服务端返回一个证书,客户端里存有各个受信任的证书机构根证书,用这些根证书对服务端 返回的证书进行验证,经验证如果证书是可信任的,就生成一个pre-master secret,用这个证书的公钥加密后发送给服务端,服务端用私钥解密后得到pre-master secret,再根据某种算法生成master secret,客户端也同样根据这种算法从pre-master secret生成master secret,随后双方的通信都用这个master secret对传输数据进行加密解密。
证书
NSURLSession 支持 cer 格式的证书文件,但是一般从管理员手里拿到的都是 crt 格式的证书,需要先安装到系统,在用钥匙串导出 cer 格式证书。
实现
如果使用AFNetworking,那么实现起来还是,首先把 cer 格式的证书拖到工程里。
然后新建AFHTTPRequestOperationManager就好了
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy = securityPolicy;`
AFSecurityPolicy这个类是AFN的设置SSL钢钉的类,有3种验证方式:
- AFSSLPinningModeNone: 这个模式表示不做SSL pinning,只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书,这里是不会通过的。(这个模式是不安全的)
- AFSSLPinningModePublicKey: 代表客户端会将服务器端返回的证书与本地保存的证书中,PublicKey的部分进行校验;如果正确,才继续进行。
- AFSSLPinningModeCertificate: 代表客户端会将服务器端返回的证书和本地保存的证书中的所有内容,包括PublicKey和证书部分,全部进行校验;如果正确,才继续进行。
2和3都需要把证书内置在 app Bundle中。
一般情况使用AFSSLPinningModePublicKey就好了,AFN的方法是读取app中所有.cer后缀的文件就行匹配。
如果直接设置AFSSLPinningModeNone,HTTPS也是能正常访问的,但是就没有校验证书,失去HTTPS的意义。
简单说:HTTP+SSL/TLS+TCP = HTTPS,只有证书匹配才会完成服务器请求,得到数据。