https信任证书的三种方

2024-09-06 12:08
文章标签 三种 https 证书 信任

本文主要是介绍https信任证书的三种方,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

苦逼的我调试AFNetworking发送https请求的bug ---------调试了一个上午,终于解决了


证书信任的过程:

证书的信任是通过代理的方式进行信任(NSURLConnection和NSURLSession两种方式进行信任)
客户端信任证书的过程:
1.当客户端要访问服务器的时候,服务器向客户端发送受保护的信任证书
2.客户端判断是否对客户端发送的证书进行信任,,
3.如果信任.则客户端会安装公钥在客户端,而服务器就拥有受保护证书的密钥,每一次向服务器请求数据的时候,服务器会先将要发送的数据进行密钥加密,客户端对所传数据通过公钥解密


下面分享一下自己的经验:

一开始请求数据先要信任证书,然后才能请求数据,不过对于百度,apple官网这样的大网站就不需要信任证书了,

只需要信任一次服务器证书

在信任证书的时候有两种方式:

大家熟知的有NSURLSession和NSURLConnection两种信任证书的方式,我会重点将第三种:

如果不信任证书的话会报下面的错误:

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

一.NSURLSession的方式信任证书是通过代理的方式:

1.先懒加载全局的会话:

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @property (nonatomicstrongNSURLSession *session;  
  2. - (NSURLSession *)session {  
  3.     if (_session == nil) {  
  4.         NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];  
  5.         _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];  
  6.     }  
  7.     return _session;  
  8. }  

2.发起数据任务

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // url  
  2.    NSURL *url = [NSURL URLWithString:@"https://域名"];  
  3.      
  4.    // 发起数据任务  
  5.    [[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {  
  6.        NSLog(@"%@---%@",response,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);  
  7.    }] resume];  

3.代理方法中实现证书的信任-----------

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task  
  2. didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge  
  3.  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {  
  4.     /* 
  5.      <NSURLProtectionSpace: 0x7fef2b686e20>:  
  6.      Host:mail.itcast.cn,  
  7.      Server:https,  
  8.      Auth-Scheme:NSURLAuthenticationMethodServerTrust, 
  9.      */  
  10.     // 判断是否是信任服务器证书  
  11.     if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {  
  1.  // 告诉服务器,客户端信任证书  
  2.         // 创建凭据对象  
  3.         NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];  
  4.         // 通过completionHandler告诉服务器信任证书  
  5.         completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);  
  6.     }  
  7.     NSLog(@"protectionSpace = %@",challenge.protectionSpace);  
  8. }  


二.NSURLConnection的方式信任证书也是通过代理的方式:

1.发送请求:

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // url  
  2. NSURL *url = [NSURL URLWithString:@"https://mail.itcast.cn"];  
  3.   
  4. // request  
  5. NSURLRequest *request = [NSURLRequest requestWithURL:url];  
  6.   
  7. // 发送请求  
  8. [NSURLConnection connectionWithRequest:request delegate:self];  

2.信任证书
[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #pragma mark - NSURLConnectionDataDelegate 代理方法  
  2. - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {  
  3.     // 判断是否是信任服务器证书  
  4.     if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {  
  5.         // 告诉服务器,客户端信任证书  
  6.         // 创建凭据对象  
  7.         NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];  
  8.         // 告诉服务器信任证书  
  9.         [challenge.sender useCredential:credntial forAuthenticationChallenge:challenge];  
  10.     }  
  11. }  
3.获取请求到的数据
[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {  
  2.     NSLog(@"data = %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);  
  3. }  

三.AFNetworking的方式信任服务器证书:

先上代码:
[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];  
  2. manager.securityPolicy.validatesDomainName = NO;  
  3. manager.responseSerializer = [AFHTTPResponseSerializer serializer];  
  4.   manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json"@"text/json"@"text/javascript",@"text/html", nil nil];  
  5. [manager GET:@"https://域名" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {  
  6.     NSLog(@"%@",downloadProgress);  
  7. } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {  
  8.     NSLog(@"%@---%@",[responseObject class],responseObject);  
  9.     NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);  
  10. } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  
  11.     NSLog(@"%@",error);  
  12. }];  


注意解释遇到的坑:
1.https的协议直接请求的时候会报下面的错:

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


2.设置属性
不能将 validatesDomainName设置为NO,当设置为NO以后可以发出任意的请求,所以要将其设置为YES(默认是YES)-----重点

manager.securityPolicy.validatesDomainName =YES;

AFNetworking 的安全相關設定放在 AFSecurityPolicy,它定義了三種 SSL Pinning Mode:

  • AFSSLPinningModeNone : 你不必將憑證跟你的 APP 一起打包,完全信任伺服器的憑證
  • AFSSLPinningModeCertificate : 比對伺服器憑證跟你的憑證是否完全匹配
  • AFSSLPinningModePublicKey : 只比對伺服器憑證的 public key 跟你的憑證的 public key 是否匹配

那要選用何種模式比較好呢?

AFSSLPinningModeCertificate 比較安全但也比較麻煩,它會比對你打包的憑證跟伺服器的憑證是否一致。因為你的憑證是跟 APP 一起打包的,這也就代表說如果你的憑證過期了或是變動了,你就得出一版新的 APP 而且舊版 APP 的憑證就失效了。你也可以在每次 APP 啟動時,就自動連到某個伺服器下載最新的憑證,不過此時這個下載連線就會是有風險的。

AFSSLPinningModePublicKey 則是只有比對憑證裡的 public key,所以即使伺服器憑證有所變動,只要 public key 不變,就能通過驗證。

所以如果你能確保每個使用者總是使用最新版本的 APP(例如是公司企業內部專用的),那就可以考慮 AFSSLPinningModeCertificate,否則的話選擇 AFSSLPinningModePublicKey 是比較實際的作法。


解决了证书信任的问题,也就是说设置上面的属性以后就可以信任证书了


但是问题没有解决:越到了经常遇到的问题,就是请求的数据打印有问题,

Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" 


原因:

这是因为 AFNetworking默认把响应结果当成json来处理,(默认manager.responseSerializer = [AFJSONResponseSerializer serializer]) ,很显然,我们请求的百度首页 返回的并不是一个json文本,而是一个html网页,但是AFNetworking并不知道,它坚信请求的结果就是一个json文本!然后固执地以json的形式去解析,显然没办法把一个网页解析成一个字典或者数组,所以产生了上述错误.

然而,我们期望它能够正确地处理这个情形,而不是提示一个错误. 
这时候 你必须告诉AFNetworking:别把这个网页当json来处理! 

解决办法:

只需要在发送请求前加入:manager.responseSerializer = [AFHTTPResponseSerializer serializer]


以上步骤就可以实现https证书的信任和正确的获取例如baidu.com首页的html的源码...


附加说明:

网页上加载的数据本质是字符串,我们将获取到的网页数据通过二进制转字符串的形式可以讲网页数据进行打印:

 NSLog(@"%@",[[NSStringalloc]initWithData:responseObjectencoding:NSUTF8StringEncoding]);






有了上面的解决办法是不是不知道如何获取凭证能,别急,下面添加如何获取制定域名的凭证:

参考链接:

http://nelson.logdown.com/posts/2015/04/29/how-to-properly-setup-afnetworking-security-connection/


这篇关于https信任证书的三种方的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141964

相关文章

如何将Python彻底卸载的三种方法

《如何将Python彻底卸载的三种方法》通常我们在一些软件的使用上有碰壁,第一反应就是卸载重装,所以有小伙伴就问我Python怎么卸载才能彻底卸载干净,今天这篇文章,小编就来教大家如何彻底卸载Pyth... 目录软件卸载①方法:②方法:③方法:清理相关文件夹软件卸载①方法:首先,在安装python时,下

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

Java终止正在运行的线程的三种方法

《Java终止正在运行的线程的三种方法》停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作,停止一个线程可以用Thread.stop()方法,但最好不要用它,本文给大家介绍了... 目录前言1. 停止不了的线程2. 判断线程是否停止状态3. 能停止的线程–异常法4. 在沉睡中停止5

Python如何获取域名的SSL证书信息和到期时间

《Python如何获取域名的SSL证书信息和到期时间》在当今互联网时代,SSL证书的重要性不言而喻,它不仅为用户提供了安全的连接,还能提高网站的搜索引擎排名,那我们怎么才能通过Python获取域名的S... 目录了解SSL证书的基本概念使用python库来抓取SSL证书信息安装必要的库编写获取SSL证书信息

Linux配置IP地址的三种实现方式

《Linux配置IP地址的三种实现方式》:本文主要介绍Linux配置IP地址的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录环境RedHat9第一种安装 直接配置网卡文件第二种方式 nmcli(Networkmanager command-line

Linux下修改hostname的三种实现方式

《Linux下修改hostname的三种实现方式》:本文主要介绍Linux下修改hostname的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下修改ho编程stname三种方式方法1:修改配置文件方法2:hFvEWEostnamectl命

nginx生成自签名SSL证书配置HTTPS的实现

《nginx生成自签名SSL证书配置HTTPS的实现》本文主要介绍在Nginx中生成自签名SSL证书并配置HTTPS,包括安装Nginx、创建证书、配置证书以及测试访问,具有一定的参考价值,感兴趣的可... 目录一、安装nginx二、创建证书三、配置证书并验证四、测试一、安装nginxnginx必须有"-

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要