A 非权威机构颁发证书的HTTPS请求一样必须先在Info.plist设置如下:
NSAppTransportSecurityNSAllowsArbitraryLoads
B AFNetworking代码设置SecurityPolicy
站点https://tv.diveinedu.com是我前面博客所讲的配置方法配置的自签名证书 。
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//允许非权威机构颁发的证书
manager.securityPolicy.allowInvalidCertificates = YES;
//也不验证域名一致性
manager.securityPolicy.validatesDomainName = NO;
//关闭缓存避免干扰测试
manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[manager GET:@"https://tv.diveinedu.com/channel/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseobject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
}];
经过如上两步设置之后,我们可以在iOS应用中访问我们采用自签名证书的HTTPS站点了 。但是这个是不安全的,因为他在没有使用HTTPS/SSL代理和使用像Charles那样的HTTPS/SSL代理的情况下都可以访问服务器资源. 完全可以说是白费功夫,只能防止“君子”在网络中用Wireshark之类来TCP抓包嗅探 。因为毕竟还是HTTPS加密了传输数据了 。那为什么我要说这样是白费功夫呢,因为这个办法不能防止中间人攻击!比如用户可以给手机设置HTTPS的SSL代理(比如Charles),完全可以在代理中看到明文数据,所以,既然用了HTTPS就要防止中间人攻击,不然还不如不用HTTPS 。
下面我们来看看怎么用Charles代理抓包工具所抓到的HTTPS传输的数据:
文章插图
上图是在mac上运行Charles工具代理抓包,真机和Mac电脑同一个局域网,并设置代理为Mac机的IP和Charles的代理端口8888,然后启动App请求网络后抓到的数据 。是不是很意外啊 。HTTPS的数据也抓出明文了 。显然这样是非常不安全的,那么当我们使用自签名证书的时候,我们该如何来在App端(客户端)严格的验证服务器的合法性呢?
4.2 正确的做法我们要在App端严格验证服务器的合法性,防止网络中间的代理或者防火墙进行中间人的攻击和证书欺骗,那么我们需要把服务器配置的证书打包到客户端程序中(私钥留服务器不要分发不用泄露,非常重要),在代码里去读取该证书/公钥信息和服务器返回的进行匹配验证. 在iOS开发中,从Xcode7和iOS9开始,Apple提升了App的网络安全性,App默认只能进行对采用权威机构签名颁发证书的Web站点进行访问(信任的HTTPS),而自签名的证书的HTTPS站点也被列为属于例外,所以我们需要在App的Info.plist中单独为我们的域名设置Exception Domains"白名单",而不是打开Allow Arbitrary Loads全部放开,设置信息如下:
文章插图
NSAppTransportSecurityNSExceptionDomainstv.diveinedu.comNSExceptionAllowsInsecureHTTPLoads
这样就不像上面那个方法那样一刀切全部放开, 而是单独为某个域名放开设置.当然上面也可以使用放开全部的设置NSAllowsArbitraryLoads为true.但是我建议使用白名单.
除此之外,要做到严格验证防止像Charles那样的中间人代理抓包,AFNetworking代码应该用如下设置:
//服务器端配置的包含公钥的证书分发到客户端后,需要转换为DER格式的证书文件.
//openssl x509 -outform der -in tv.diveinedu.com.crt -out tv.diveinedu.com.der
NSString *certFilePath = [[NSBundle mainBundle] pathForResource:@"tv.diveinedu.com" ofType:@"der"];
NSData *certData = https://www.isolves.com/it/wl/aq/2022-02-11/[NSData dataWithContentsOfFile:certFilePath];
NSSet *certSet = [NSSet setWithObject:certData];
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey withPinnedCertificates:certSet];
policy.allowInvalidCertificates = YES;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = policy;
//关闭缓存避免干扰测试
manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[manager GET:@"https://tv.diveinedu.com/channel/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
}];
上面的代码能够验证服务器身份在没有使用代理的时候可以正常访问服务器的资源,但是一旦用户给手机网络设置使用了如Charle那样的HTTPS/SSL代理服务,则会出现服务器证书验证失败,SSL网络连接会断开,老板再也不用担心数据接口被人抓包或者代理给扒出来了.故达到防止中间人攻击的效果.
推荐阅读
- 大红袍|紫砂乱象之——紫砂壶泥料(上)
- 网络安全单兵工具 -- YAKIT
- 2022年VMware七大网络安全预测
- Java 日志记录—记录什么和不记录什么?
- 服务器安全篇:最可怕的搜索引擎 运维必备之——Shodan
- FFmpeg 开发——将视频 YUV 格式编码成 H264
- 发型|中学生“不良发型”图示,每一个都很经典,发型能防止早恋吗?
- 一起学排序算法——选择排序
- cpolar——安全的内网穿透工具
- 红茶心脏病,冬天红茶种类