今天有朋友在做一个金融APP的 时候,在提交银联审核时,因为SSLPining的问题被拒掉,被拒原因:尽管客户端使用了HTTPS进行通信,但如果用户的手机遭到诱导安装自签名证书,也会遭到中间人攻击,解密通信流量。
解决问题方案如下:
1.APP用的是AF2.X,版本有点老,而AF在2.6版本后SSL的设置方法发生了改变,所以先进行了版本的更新
2.在升级后,使用HTTPS在验证证书时设置AFSSLPinningMode,废话不说,上代码。
先介绍一下AFSSLPinningMode,有三个属性
AFSSLPinningModeNone
这个模式表示不做SSL pinning,只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书,这里是不会通过的。
AFSSLPinningModeCertificate
这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名/有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。
这里还没弄明白第一步的验证是怎么进行的,代码上跟去系统信任机构列表里验证一样调用了SecTrustEvaluate,只是这里的列表换成了客户端保存的那些证书列表。若要验证这个,是否应该把服务端证书的颁发机构根证书也放到客户端里?
AFSSLPinningModePublicKey
这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。
使用方法:
AFHTTPSessionManager *httpSessionManager = [AFHTTPSessionManager manager];
[httpSessionManager setSecurityPolicy:[self customSecurityPolicy]];
httpSessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
- (AFSecurityPolicy*)customSecurityPolicy
{
// /先导入证书
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"smk" ofType:@"cer"];//证书的路径
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
// AFSSLPinningModeCertificate 使用证书验证模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
// 如果是需要验证自建证书,需要设置为YES
securityPolicy.allowInvalidCertificates = YES;
[AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = @[certData];
return securityPolicy;
}
当然在过程中也参考了一下的博客:
iOS安全系列之二:HTTPS进阶
如何使用SSL pinning来使你的iOS APP更加安全 - Kakarotto-卡卡罗特 - 博客园
正确使用AFNetworking的SSL保证网络安全 -
如何正確設定 AFNetworking 的安全連線 « Nelson 寫些 iOS 開發的東東
如果你觉得本文对你有帮助,点赞或者收藏啦啦啦
整个AFSecurityPolicy就是实现这这几种验证方式,剩下的就是实现细节了,详见源码。