AFNetworking 3.0 源码解读(二)之 AFSecurityPolicy
这个是网络完全策略类(其实就是验证证书是否安全),https其实就是给http加了一层SSL外衣,让传输过层更加的安全,因为http在网络上是明文传输的。
HTTP:
1.HTTP协议用于客户端和服务器端之间的通信
2.通过请求和相应的交换达成通信
客户端请求:
服务器端响应:
3.HTTP是不保存状态的协议
HTTP自身不会对请求和相应之间的通信状态进行保存。什么意思呢?就是说,当有新的请求到来的时候,HTTP就会产生新的响应,对之前的请求和响应的保温信息不做任何存储。这也是为了快速的处理事务,保持良好的可伸展性而特意设计成这样的。
4.请求URI定位资源
URI算是一个位置的索引,这样就能很方便的访问到互联网上的各种资源。
5.告知服务器意图的HTTP方法
①GET: 直接访问URI识别的资源,也就是说根据URI来获取资源。
②POST: 用来传输实体的主体。
③PUT: 用来传输文件。
④HEAD: 用来获取报文首部,和GET方法差不多,只是响应部分不会返回主体内容。
⑤DELETE: 删除文件,和PUT恰恰相反。按照请求的URI来删除指定位置的资源。
⑥OPTIONS: 询问支持的方法,用来查询针对请求URI指定的资源支持的方法。
⑦TRACE: 追踪路径,返回服务器端之前的请求通信环信息。
⑧CONNECT: 要求用隧道协议连接代理,要求在与代理服务器通信时简历隧道,实现用隧道协议进行TCP通信。SSL(Secure Sockets Layer)和TLS(Transport Layer Security)就是把通信内容加密后进行隧道传输的。
6.管线化让服务器具备了相应多个请求的能力
7.Cookie让HTTP有迹可循
HTTP是一套很简单通信协议,因此也非常的高效。但是由于通信数据都是明文发送的,很容易被拦截后造成破坏。在互联网越来越发达的时代,对通信数据的安全要求也越来越高。
HTTPS
HTTPS是一个通信安全的解决方案,可以说相对已经非常安全。为什么它会是一个很安全的协议呢?下边会做出解释
大家可以看看这篇文章,解释的很有意思 。
HTTP + 加密 + 认证 + 完整性保护 = HTTPS
其实HTTPS是身披SSL外壳的HTTP,这句话怎么理解呢?
大家应该都知道HTTP是应用层的协议,但HTTPS并非是应用层的一种新协议,只是HTTP通信接口部分用SSL或TLS协议代替而已。
通常 HTTP 直接和TCP通信,当使用SSL时就不同了。要先和SSL通信,再由SSL和TCP通信。
这里再说一些关于加密的题外话:
现如今,通常加密和解密的算法都是公开的。举个例子: a * b = 200,加入a是你知道的密码,b是需要被加密的数据,200 是加密后的结果。那么这里这个*号就是一个很简单的加密算法。这个算法是如此简单。但是如果想要在不知道a和b其中一个的情况下进行**也是很困难的。就算我们知道了200 然后得到a b 这个也很难。假设知道了密码a 那么b就很容易算出b = 200 / a 。
实际中的加密算法比这个要复杂的多。
介绍两种常用加密方法:
1.共享**加密
2.公开**加密
共享**加密就是加密和解密通用一个**,也称为对称加密。优点是加密解密速度快,缺点是一旦**泄露,别人也能解密数据。
公开**加密恰恰能解决共享**加密的困难,过程是这样的:
①发文方使用对方的公开**进行加密
②接受方在使用自己的私有**进行解密
关于公开**,也就是非对称加密 可以看看这篇文章 RSA算法原理
原理都是一样的,这个不同于刚才举得a和b的例子,就算知道了结果和公钥,**出被机密的数据是非常难的。这里边主要涉及到了复杂的数学理论。
HTTPS采用混合加密机制
HTTPS采用共享**加密和公开**加密两者并用的混合加密机制。
好了我们大概已经知道了HTTPS是如何加密的了,那么这个相互认证过程是怎么样的呢 ?
在网上看到了这篇博客,http://blog.****.net/yuwuchaio/article/details/50469183 把他描述的剪切下来了
==================================================================
==================================================================
注意黄色的部分,这个指明了,我们平时使用的一个场景。这篇文章会很长,不仅仅是为了解释HTTPS,还为了能够增加记忆,当日后想看看的时候,就能通过读这边文章想起大部分的HTTPS的知识。下边解释一些更加详细的HTTPS过程。
一 :分析头文件
还是先看头文件里边有什么东西。要实现认证功能需要添加系统的Security,这个是必须的。
下边的这个枚举值的意思的是:
1. AFSSLPinningModeNone 代表无条件信任服务器的证书
2. AFSSLPinningModePublicKey 代表会对服务器返回的证书中的PublicKey进行验证,通过则通过,否则不通过
3. AFSSLPinningModeCertificate 代表会对服务器返回的证书同本地证书全部进行校验,通过则通过,否则不通过
说的是AFSecurityPolicy 用来评价通过X.509(数字证书的标准)的数字证书和公开**进行的安全网络连接是否值得信任。在应用内添加SSL证书能够有效的防止中间人的攻击和安全漏洞。强烈建议涉及用户敏感或隐私数据或金融信息的应用全部网络连接都采用使用SSL的HTTPS连接。
返回SSL Pinning的类型。默认的是AFSSLPinningModeNone。
这个属性保存着所有的可用做校验的证书的集合。AFNetworking默认会搜索工程中所有.cer的证书文件。如果想制定某些证书,可使用certificatesInBundle在目标路径下加载证书,然后调用policyWithPinningMode:withPinnedCertificates创建一个本类对象。
注意: 只要在证书集合中任何一个校验通过,evaluateServerTrust:forDomain: 就会返回true,即通过校验。
使用允许无效或过期的证书,默认是不允许。
是否验证证书中的域名domain
返回指定bundle中的证书。如果使用AFNetworking的证书验证 ,就必须实现此方法,并且使用policyWithPinningMode:withPinnedCertificates 方法来创建实例对象。
默认的实例对象,默认的认证设置为:
1. 不允许无效或过期的证书
2. 验证domain名称
3. 不对证书和公钥进行验证
这两个方法没什么好说的,都是创建security policy 的方法。
核心方法:使用起来是这样的,这个方法AFNetworking在内部调用了。这个后边会说到
1 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 2 3 AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init]; 4 [securityPolicy setAllowInvalidCertificates:NO]; 5 [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; 6 [securityPolicy setValidatesDomainName:YES]; 7 [securityPolicy setValidatesCertificateChain:NO]; 8 9 manager.securityPolicy = securityPolicy;
// 在证书中获取公钥 static id AFPublicKeyForCertificate(NSData *certificate) 这个方法中别的了解就行了, 需要了解#import <AssertMacros.h>中的宏
__Require_Quiet 和 __Require_noErr_Quiet 这两个宏定义。
__Require_Quiet()其实就是为真执行标记之间的代码,用着比较方便
__Require_noErr_Quiet ()出现异常会跳过之间的代码。
把key转成datastatic NSData * AFSecKeyGetData(SecKeyRef key)
static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2)
SecKeyRef是一个stuct 结构体,所有要转成data进行比较。
1.用户自定义的,成功是 kSecTrustResultProceed 失败是kSecTrustResultDeny
2.非用户定义的, 成功是kSecTrustResultUnspecified 失败是kSecTrustResultRecoverableTrustFailure
这就不难解释上边最后的那个或判断了。
static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) 取出服务器返回的所有证书
static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) 取出服务器返回的所有证书的公钥
+ (NSSet *)certificatesInBundle:(NSBundle *)bundle 获取项目包中的所有.cer证书
+ (NSSet *)defaultPinnedCertificates
// 找到相同的公钥就通过 73 for (id trustChainPublicKey in publicKeys) { 74 for (id pinnedPublicKey in self.pinnedPublicKeys) { 75 if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { 76 trustedPublicKeyCount += 1; 77 } 78 } 79 }
下面的都是归档的内容。
在这里推荐一篇不错的文章 iOS 9之适配ATS