深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求(三)

简介: 深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求

五、iOS开发中通过配置info.plist文件来允许HTTP协议类型的通讯


     前面扯了太多,终于提到重点部分了。Apple在iOS9中就已经漏出一些强制HTTPS通讯的端倪,只是给了开发者一些过渡,在iOS10及以后的审核机制中,Apple对于强制HTTPS的推动将会越来越强,如何让自己的应用程序尽快的适配HTTPS相关的标准,是iOS开发者必须面对的任务。


     通过前面的分析我们了解,CA机构签发的证书是被默认信任的,这就是说,如果你的公司比较有钱,愿意花钱从CA机构申请一个付费的证书,那么很幸运,你的iOS工程是不需要做任何修改的,这些CA机构签发的证书是默认受信任的,因此你可以直接在程序中进行HTTPS类型的请求,所需要修改的只是将请求url改成https开头。但是另一种情况,无论出于什么原因,你的后台服务用的是自签名的证书,就想我们上面搭建的HTTPS服务一样,如果在不做任何处理的情况下在项目中访问这样的服务,就会出现问题了,原因是我们自己创建的自签名证书是不受信任的,系统默认拒绝了请求,示例如下:


-(void)normalHttps{

   NSURLRequest * req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://localhost:8080/users"]];

   NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];

   NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];

   [[session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

       NSLog(@"%@,%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);

   }] resume];

}

运行工程后可以看到,并没有获取到相关数据,Xcode提示为:


NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

好了,那么我们先不管HTTPS的问题,如果我们直接对HTTP协议的服务进行请求,会不会有问题呢,将代码修改如下:


-(void)normalHttps{

   NSURLRequest * req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:3000/users"]];

   NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];

   NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];

   [[session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

       NSLog(@"%@,%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);

   }] resume];

}

需要注意:Express在进行项目模板的创建时,会默认帮我们绑定一个3000端口的HTTP服务。


运行工程后,可以发现HTTP协议的请求也无法访问,报错如下:


App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

其意思大致是说应用程序传输安全要求强制使用HTTPS类型的服务,但是开发者可以通过配置info.plsit文件来回避这一政策。这就是我们这节的重点,通过文件配置的方式来跳过应用安全传输协议。


   在iOS9之后,开发者可以在Info.plist文件中添加如下键:NSAppTransportSecurity。这个键用来配置APP传输安全的相关策略,是字典类型,其中可以设置的键有五个,如下:


NSAllowsArbitraryLoads:布尔值,默认为NO,设置为YES则代表除了NSExceptionDomains中设置的域名外,其他所有请求的协议类型都不受限制,也就是说可以支持HTTP类型的请求,这个键的作用域是全局的,App内所有的请求都受影响,但是如果开发者设置为了YES,在提交审核时需要说明原因。


NSAllowsArbitraryLoadsForMedia:布尔值,默认为NO,设置为YES的话,则应用程序内所有的媒体数据的加载将不受协议类型的限制,同样如果开发者设置为了YES,则在提交审核时需要说明原因。


NSAllowsArbitraryLoadsInWebContent:布尔值,默认为NO。如果设置为YES,则应用程序内所有WebView的请求加载不受协议类型的限制,开发者设置为了YES,则在提交审核时需要说明原因。


NSAllowsLocalNetworking:布尔值,默认为NO,如果设置为YES,则在加载本地资源时不受安全传输协议的限制。


NSExceptionDomains:字典,其主要对某些特殊域名做限制。其中结构可以表示如下:


NSAppTransportSecurity : Dictionary {

   NSAllowsArbitraryLoads : Boolean

   NSAllowsArbitraryLoadsForMedia : Boolean

   NSAllowsArbitraryLoadsInWebContent : Boolean

   NSAllowsLocalNetworking : Boolean

   //对某些域名做特殊限制

   NSExceptionDomains : Dictionary {

       <domain-name-string> : Dictionary {

           NSIncludesSubdomains : Boolean

           NSExceptionAllowsInsecureHTTPLoads : Boolean

           NSExceptionMinimumTLSVersion : String

           NSExceptionRequiresForwardSecrecy : Boolean   // Default value is YES

           NSRequiresCertificateTransparency : Boolean

       }

   }

}

NSIncludesSubdomains:布尔值,这个键的作用是设置此域名下的所有子域名是否采用和父域名相同的配置。


NSExceptionAllowsInsecureHTTPLoads:布尔值,设置是否允许此域名使用自签名的证书进行请求,默认为NO,如果设置为YES,则在提交时需要说明原因。


NSExceptionMinimumTLSVersion:设置所使用的TLS版本。


NSExceptionRequiresForwardSecret:设置为NO,则不允许向前加密方式。


NSRequiresCertificateTransparency:如果设置为YES,则服务端的证书要有有效的透明时间戳。

六、iOS中使用自签名的证书进行HTTPS请求校验


   通过Info.plist文件我们是可以绕过安全传输协议的,但是不幸的是,从文档上看,无论开发者通过哪种方式来绕过安全传输协议,Apple都要求开发者在提审时提供合适的理由,这就是说:如果你使用了HTTP协议的请求,没有充足理由的话,你的App有很大的可能被审核拒绝。因此,更加保险的一种方式是将所有的服务都换成HTTPS协议的,如果有CA证书,当然完事大吉,如果没有,我们也可以通过验证自签名证书的方式来适配HTTPS协议。


   在进行HTTPS请求时,服务端会先将证书文件返回给客户端,如果客户端的证书信任列表中包含这个证书,则此请求可以正常进行,如果没有,则请求会被拒绝。因此,在iOS中适配自签名证书的HTTPS请求实际上就是将这个自签名的证书安装进客户端的信任列表。iOS中需要使用的证书是der格式的,可以使用如下命令将pem格式的证书转换成der格式的证书:


openssl x509 -inform PEM -in cert.pem -outform DER -out cert.der

将生成的cert文件添加进工程中,修改请求如下:


-(void)normalHttps{

   NSURLRequest * req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://localhost:8080/users"]];

   NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];

   NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

   NSURLSessionTask * task = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

       NSLog(@"%@,%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);

   }];

   [task resume];

}

除此之外,需要实现一个SURLSessionDelegate的协议方法如下:


- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge

completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {

   NSLog(@"证书认证");

   //先判断证书是否有效

   if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {

       //证书验证请求

       SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];

       /**

        *  导入多张CA证书(Certification Authority,支持SSL证书以及自签名的CA)

        */

       NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"cert" ofType:@"der"];//自签名证书

       NSData* caCert = [NSData dataWithContentsOfFile:cerPath];

       //可以添加多张证书

       NSArray *caArray = @[caCert];

       //验证规则

       NSMutableArray *policies = [NSMutableArray array];

       [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];

       SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);

       NSMutableArray *pinnedCertificates = [NSMutableArray array];

       //进行自签名证书的添加

       for (NSData *certificateData in caArray) {

           [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];

       }

       SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);

       SecTrustResultType result = -1;

       //通过本地导入的证书来验证服务器的证书是否可信

       SecTrustEvaluate(serverTrust, &result);

       NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];

       completionHandler(NSURLSessionAuthChallengeUseCredential,credential);

       return [[challenge sender] useCredential: credential

                     forAuthenticationChallenge: challenge];

     

   }

}

如上修改后,再次运行工程,可以看到已经成功请求到了HTTPS自签名证书服务提供的数据:


image.png

相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
24天前
|
Ubuntu Windows
【Ubuntu/Arm】Ubuntu 系统如何链接有线网络(非虚拟机)?
【Ubuntu/Arm】Ubuntu 系统如何链接有线网络(非虚拟机)?
|
1月前
|
机器学习/深度学习 数据采集 人工智能
m基于深度学习网络的手势识别系统matlab仿真,包含GUI界面
m基于深度学习网络的手势识别系统matlab仿真,包含GUI界面
41 0
|
1月前
|
消息中间件 网络协议 C++
C/C++网络编程基础知识超详细讲解第三部分(系统性学习day13)
C/C++网络编程基础知识超详细讲解第三部分(系统性学习day13)
|
1月前
|
存储 Shell Linux
【Shell 命令集合 网络通讯 】Linux 显示Unix-to-Unix Copy (UUCP) 系统的状态信息 uustat命令 使用指南
【Shell 命令集合 网络通讯 】Linux 显示Unix-to-Unix Copy (UUCP) 系统的状态信息 uustat命令 使用指南
26 0
|
1月前
|
Shell Linux C语言
【Shell 命令集合 网络通讯 】Linux 查看系统中的UUCP日志文件 uulog命令 使用指南
【Shell 命令集合 网络通讯 】Linux 查看系统中的UUCP日志文件 uulog命令 使用指南
29 0
|
15天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
39 6
|
22小时前
|
机器学习/深度学习 算法 计算机视觉
m基于Yolov2深度学习网络的人体喝水行为视频检测系统matlab仿真,带GUI界面
MATLAB 2022a中使用YOLOv2算法对avi视频进行人体喝水行为检测,结果显示成功检测到目标。该算法基于全卷积网络,通过特征提取、锚框和损失函数优化实现。程序首先打乱并分割数据集,利用预训练的ResNet-50和YOLOv2网络结构进行训练,最后保存模型。
10 5
|
10天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
10 0
|
16天前
|
JavaScript Java 测试技术
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
30 0
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
|
19天前
|
机器学习/深度学习 人工智能 运维
构建未来:AI驱动的自适应网络安全防御系统
【4月更文挑战第7天】 在数字时代的浪潮中,网络安全已成为维系信息完整性、保障用户隐私和确保商业连续性的关键。传统的安全防御策略,受限于其静态性质和对新型威胁的响应迟缓,已难以满足日益增长的安全需求。本文将探讨如何利用人工智能(AI)技术打造一个自适应的网络安全防御系统,该系统能够实时分析网络流量,自动识别并响应未知威胁,从而提供更为强大和灵活的保护机制。通过深入剖析AI算法的核心原理及其在网络安全中的应用,我们将展望一个由AI赋能的、更加智能和安全的网络环境。
28 0