深入理解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

目录
相关文章
|
11月前
|
机器学习/深度学习 算法 机器人
【PID】基于人工神经网络的PID控制器,用于更好的系统响应研究(Matlab&Simulink代码实现)
【PID】基于人工神经网络的PID控制器,用于更好的系统响应研究(Matlab&Simulink代码实现)
1290 16
|
11月前
|
机器学习/深度学习 数据采集 传感器
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
690 0
|
12月前
|
数据采集 存储 算法
MyEMS 开源能源管理系统:基于 4G 无线传感网络的能源数据闭环管理方案
MyEMS 是开源能源管理领域的标杆解决方案,采用 Python、Django 与 React 技术栈,具备模块化架构与跨平台兼容性。系统涵盖能源数据治理、设备管理、工单流转与智能控制四大核心功能,结合高精度 4G 无线计量仪表,实现高效数据采集与边缘计算。方案部署灵活、安全性高,助力企业实现能源数字化与碳减排目标。
436 0
|
9月前
|
Ubuntu 网络协议 网络安全
解决Ubuntu系统的网络连接问题
以上步骤通常可以帮助解决大多数Ubuntu系统的网络连接问题。如果问题仍然存在,可能需要更深入的诊断,或考虑联系网络管理员或专业技术人员。
2099 18
|
9月前
|
监控 安全 网络协议
Cisco Identity Services Engine (ISE) 3.5 发布 - 基于身份的网络访问控制和策略实施系统
Cisco Identity Services Engine (ISE) 3.5 发布 - 基于身份的网络访问控制和策略实施系统
866 1
Cisco Identity Services Engine (ISE) 3.5 发布 - 基于身份的网络访问控制和策略实施系统
|
9月前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的青少年网络使用情况分析及预测系统
本研究基于Python大数据技术,构建青少年网络行为分析系统,旨在破解现有防沉迷模式下用户画像模糊、预警滞后等难题。通过整合多平台亿级数据,运用机器学习实现精准行为预测与实时干预,推动数字治理向“数据驱动”转型,为家庭、学校及政府提供科学决策支持,助力青少年健康上网。
|
11月前
|
安全 KVM 虚拟化
Cisco Identity Services Engine (ISE) 3.4 - 基于身份的网络访问控制和策略实施系统
Cisco Identity Services Engine (ISE) 3.4 - 基于身份的网络访问控制和策略实施系统
618 2
Cisco Identity Services Engine (ISE) 3.4 - 基于身份的网络访问控制和策略实施系统
|
10月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
628 2
|
11月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
696 18