正确设定AFNetworking的安全连接

为什么突然这么一讲?

1.之前苹果公司在iOS9的时候,建议大家将Allow Arbitrary Loads 设置成NO,然后充分利用HTTPS发送网络和接收数据,保证数据安全;
2.这几天一直看AFN的源码,到了AFSecurityPolicy这一类中,但是看到了AFN在我们项目中使用没有太多的调用该类;
3.之前适配HTTPS的时候,有朋友说需要在Xcode中配置一下.cer,有的朋友说不需要也可以正常使用AFN;
4.很多点自己也不是特别理解,比较混乱;


HTTPS的流程图
正确设定AFNetworking的安全连接_第1张图片
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 neededAdd to targets

正确设定AFNetworking的安全连接_第2张图片
效果

  • 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 的安全連線

你可能感兴趣的:(正确设定AFNetworking的安全连接)