深入理解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博客。
目录
相关文章
|
19天前
|
搜索推荐 Android开发 iOS开发
安卓与iOS系统的用户界面设计对比分析
本文通过对安卓和iOS两大操作系统的用户界面设计进行对比分析,探讨它们在设计理念、交互方式、视觉风格等方面的差异及各自特点,旨在帮助读者更好地理解和评估不同系统的用户体验。
18 1
|
2月前
|
搜索推荐 Android开发 iOS开发
探析安卓与iOS系统的优劣
【2月更文挑战第7天】安卓与iOS是当今手机市场上最主流的两款操作系统,各有优劣。本文将从用户体验、开放程度、生态系统等方面对两者进行深入探析,以期帮助读者更好地了解它们的特点。
|
2月前
|
Android开发 数据安全/隐私保护 iOS开发
安卓与iOS系统的发展趋势与比较分析
【2月更文挑战第6天】 在移动互联网时代,安卓和iOS系统作为两大主流移动操作系统,各自呈现出不同的发展趋势。本文将从技术角度出发,对安卓和iOS系统的发展方向、特点及未来趋势进行比较分析,以期为读者提供更深入的了解和思考。
32 4
|
5月前
|
算法 Linux 网络安全
Centos7 Linux系统下生成https的crt和key证书
Centos7 Linux系统下生成https的crt和key证书
183 0
|
1月前
|
机器学习/深度学习 测试技术 API
iOS系统下轻松构建自动化数据收集流程
iOS系统下轻松构建自动化数据收集流程
19 0
|
1月前
|
Web App开发 前端开发 网络安全
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
【2月更文挑战第21天】前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
46 1
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
|
1月前
|
搜索推荐 安全 Android开发
安卓与iOS系统的用户体验比较
【2月更文挑战第11天】 在当今移动设备市场上,安卓和iOS系统一直是两大主流操作系统。本文将从用户界面设计、应用生态、系统定制性等方面对安卓和iOS系统进行比较分析,旨在探讨两者的优势和劣势,为用户选择合适的操作系统提供参考。
|
2月前
|
人工智能 vr&ar Android开发
探索安卓与iOS系统的发展趋势
【2月更文挑战第9天】 过去,人们对于安卓和iOS系统的争论主要集中在性能、用户体验和生态系统的比较上。然而,随着移动互联网的快速发展,两大操作系统在人工智能、物联网、安全性等方面的发展趋势也备受关注。本文将探讨安卓与iOS系统在技术发展方面的差异以及未来的发展趋势。
|
2月前
|
搜索推荐 Android开发 iOS开发
探讨安卓与iOS系统的用户体验差异
【2月更文挑战第7天】 在当今移动互联网时代,安卓和iOS系统是最受欢迎的手机操作系统。本文将从用户界面设计、应用生态系统、定制性能等方面探讨安卓与iOS系统的用户体验差异,为读者提供更深入的了解。
|
2月前
|
安全 开发工具 Android开发
安卓与iOS系统的优缺点比较
【2月更文挑战第6天】 安卓和iOS是目前市场上最流行的两种操作系统。虽然它们都拥有自己的独特之处,但它们也有一些共同之处。本文将探讨这两种操作系统的优缺点,并对它们进行比较。