为什么突然这么一讲?
1.之前苹果公司在iOS9的时候,建议大家将Allow Arbitrary Loads 设置成NO
,然后充分利用HTTPS
发送网络和接收数据,保证数据安全;
2.这几天一直看AFN的源码,到了AFSecurityPolicy
这一类中,但是看到了AFN在我们项目中使用没有太多的调用该类;
3.之前适配HTTPS
的时候,有朋友说需要在Xcode中配置一下.cer
,有的朋友说不需要也可以正常使用AFN;
4.很多点自己也不是特别理解,比较混乱;
HTTPS的流程图
图例说明:
1.发送HTTPS请求;
2.后台有一套AC证书,公钥私钥;
3.在公钥中设置了加密算法(有的人说在client端设置的,但是我看一些文章是在公钥,而且返回的证书中有算法的名称,可信度较高,我没有去做过多的研究),然后直接将crt的公钥返回客户端;
4.在client段使用之前的放置好的“后台给的cer证书”,去和后台response的公钥比较一下,看看是不是可信任的;(SSL在这里使用到了)
5.如果可信,那么生成一个randomkey,就是随机数,然后将随机数放到公钥中加密保存,传递回去;(此时其他第三方及时获取了公钥,也无法打开,因为这个只有私钥能够打开)
6.服务端通过私钥打开公钥,获取随机数,然后用随机数打包加密要传递的数据;
7.通过刚才生成的随机数打开服务器返回的数据
为什么用HTTPS?
HTTP过去一直使用,但是容易被其他人获取到数据,会造成数据泄露,影响用户安全;
HTTPS是多添加了SSL层,帮助我们通过SSL层,加密数据,让第三方无法获取数据;
SSL层都有什么模式,每种模式的作用是什么?
SSL Pinning
在AFN中经常看到,我们翻译成证书绑定
,说白了就是将证书放到项目中Supporting Files
这个文件夹就行SSL的模式:
typedef NS_ENUM(NSUInteger, AFSSLPinningMode)
{
AFSSLPinningModeNone,
AFSSLPinningModePublicKey,
AFSSLPinningModeCertificate,
};
AFSSLPinningModeNone
无条件信任后台返回来的证书,AFN默认就是这个,大多数使用AFN的人都是用的这个,使用这个,不用往项目中添加cer证书;但是不安全,因为这个没有任何验证
AFSSLPinningModePublicKey
要去验证服务器中的公钥,这个是特别推荐使用的,即使证书过期了,也可以使用,因为只去验证公钥,此时,要在Xcode项目中,放置后台的cer证书供AFN去遍历查询使用
AFSSLPinningModeCertificate
去验证证书,这个不推荐,费力不讨好,而且一旦证书过期了,那么就要想办法去更新一下,因为一个CA证书,可能是有很多机构一级一级的颁发,所以其中一个过期了,验证就不正确了,所以就要去更新,在app中我们每一次都要去更新,但是不安全,有有可能第三方在这个时候,他们做中间的攻击;这种模式,也要在Xcode中放置后台的cer证书
AFSecurityPolicy是个啥
- 当发送网络请求的时候,我们和后台要链接的时候,可能要接收到后台服务器的
认证挑战(authentication challenge)
,就是看看咱们是不是一伙的。要去认证的时候,客户端要去看看后台发来的证书是不是“受信”的,说白了,就是能不能信任他。如果能信任,那么发送一个凭证(Credential)
给服务器去接收挑战; - 验证证书是否正确的方法是
[AFSecurityPolicy evaluateServerTrust:forDomain:]
- AFN的安全类,用于保证数据传输的安全
/**
Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`.
这里面AFN会自动遍历项目中的所有cer证书,将来只要你的SSLMode是certificate或者是PublicKey,那么这里面是要有证书的
*/
@property (nonatomic, strong, nullable) NSSet *pinnedCertificates;
/**
Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`.
1.是否允许未验证的证书,这个默认是no,每一个iOS版本,都有一个list,装有AC证书,如果不在这列表中的,都是invalid;这个属性一班用于测试情况,建议是用NO;
2.但是如果你们后台自己建立了公钥和私钥,没有通过AC机构颁发,这个字段是要使用YES的,AFN充分考虑了这个情况
*/
@property (nonatomic, assign) BOOL allowInvalidCertificates;
/**
Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`.
1.在公钥中,有访问的域名,Domain,一般要去验证一下,这个是保证不会出错的一个关键点
*/
@property (nonatomic, assign) BOOL validatesDomainName;
//这个方法是AFNSession接收挑战的时候,用这个去验证一下`服务器授信`是不是可以信任
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
forDomain:(nullable NSString *)domain;
如何安全的访问服务器数据?
1.使用HTTPS请求
2.在Xcode中配置cer证书
3.正确的配置AFN的安全策略
step1.使用HTTPS请求
1.确定一下你们后台使用的HTTPS请求,如果不是,那就算了;
2.Allow Arbitrary Loads 设置成NO,说不好哪天苹果直接给你打回来了-
step2.在Xcode中配置cer证书
1.向后台人员要.cer
证书
2.如果后台没有.cer
文件,只有.crt
文件,那么通过一下指令修改,使用DER格式编码//myWebsite这个名字是你自己起的 openssl x509 -in myWebsite.crt -out myWebsite.cer -outform der
3.如果他们也没有这个证书,那么你需要自己配置一下
//mywebsite 换成自己的
openssl s_client -connect www.mywebsite.com:443 /dev/null | openssl x509 -outform DER > myWebsite.cer
4.将.cer
文件导入到Xcode中
切结选择Copy items if needed
和Add to targets
- step3.设置AFN的配置
@interface APIManager : AFHTTPSessionManager
+ (APIManager *)sharedInstance;
@end
@implementation APIManager
+ (APIManager *)sharedInstance {
static APIManager *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
_sharedClient = [[APIManager alloc] initWithBaseURL:nil sessionConfiguration:sessionConfiguration];
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
policy.validatesCertificateChain = NO; // v2.6.0 之後沒有這個選項了
_sharedClient.securityPolicy = policy;
});
return _sharedClient;
}
@end
https原理:证书传递、验证和数据加密、解密过程解析
正确使用AFNetworking的SSL保证网络安全 - CocoaChina_让移动开发更简单
如何正確設定 AFNetworking 的安全連線