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

证书信任的过程:

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

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

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

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

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

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

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

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

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

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

[objc] view plain copy  
  1. @property (nonatomic, strong) NSURLSession *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  
  1. // url
  2. NSURL *url = [NSURL URLWithString:@"https://域名"];
  3. // 发起数据任务
  4. [[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  5. NSLog(@"%@---%@",response,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
  6. }] resume];

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

[objc] view plain copy  
  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  
  1. // url
  2. NSURL *url = [NSURL URLWithString:@"https://mail.itcast.cn"];
  3. // request
  4. NSURLRequest *request = [NSURLRequest requestWithURL:url];
  5. // 发送请求
  6. [NSURLConnection connectionWithRequest:request delegate:self];

2.信任证书

[objc] view plain copy  
  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  
  1. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  2. NSLog(@"data = %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
  3. }

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

先上代码:
[objc] view plain copy  
  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信任证书的三种方相关推荐

  1. https信任证书的三种方式

    苦逼的我调试AFNetworking发送https请求的bug ---------调试了一个上午,终于解决了 证书信任的过程: 证书的信任是通过代理的方式进行信任(NSURLConnection和NS ...

  2. ios 开发者证书付费三种类型区别

    ios 开发者证书付费三种类型区别 苹果开发者账号分为 个人(individual),公司(company),企业(enterprise)三种类型. 1.个人开发者账号: (1)费用:99美元每年. ...

  3. Java创建数组的三种方法和ArrayList的用法

    Java创建数组的三种方法和ArrayList的用法 Java创建数组的三种方法 一.声明并赋值 二.声明数组名开辟空间 三.声明数组并指定元素个数 四.多维数组 ArrayList的用法 一.添加元 ...

  4. React组件进阶--组件通讯介绍,组件的 props特点,组件通讯的三种方式子到父,父到子,兄弟到兄弟组件,Context,回顾练习

    1.组件通讯介绍 组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据(state). 在组件化过程中,我们将一个完整的功能 拆分成多个组件,以更好的完成整个应用的功能. 而在这个过程中,多个组 ...

  5. html form提交前md5,javascript实现MD5加密-JavaScript获取HTML元素的三种方...-兼容IE与firefox的js回车提交表单_169IT.COM...

    本文介绍JavaScript获取网页中HTML元素的三种方法,供大家学习参考. 1.getElementById() getElementById()可以访问DOCUMENT中的某一特定元素,顾名思义 ...

  6. android唤醒音乐播放器,android调用音乐播放器,三种方

    小弟想请问一下.怎样在自己写的程序中调用系统的音乐播放器呢. 我在google上搜索了.主要是有两种方法,可是都不是我想要的. 第一种是.使用mp3音乐文件的uri.和intent,进行调用.可是这样 ...

  7. SpringBoot 配置 HTTPS 安全证书的两种方案

    点击关注公众号,实用技术文章及时了解 文章目录 使用JDK自带的工具生成证书 使用FreeSSL提供的证书 使用JDK自带的工具生成证书 1.确保安装了JDK并正确配置了环境变量: 2.进入你的JAV ...

  8. 撤销前进快捷键_ps怎么撤销的三种方法和ps撤销快捷键以及连续撤销多步快捷键...

    内容提要:文章综合介绍ps撤销快捷键相关的一些操作,包括PS怎么撤销.PS撤销多步.ps连续撤销快捷键.历史记录面板操作等等. 关于ps怎么撤销操作,有多种方法:使用PS撤销快捷键.编辑菜单.文件菜单 ...

  9. 公众号如何让更多人看到?这三种方法超有效!

    我们做公众号运营很头疼的一个问题就是公众号如何让更多人看到? 运营公众号的目的是什么?当然是希望越来越多的用户通过公众号了解到我们,然后熟悉我们,甚至是信任我们达到转化的效果. 现在很多人迈出这第一步 ...

最新文章

  1. VGA12h与VGA寄存器
  2. 动态规划---最长公共子序列
  3. Brilliant Programmers Show
  4. 云服务器怎么选系统,云服务器怎么选择操作系统
  5. Candy Box (easy version)
  6. 只读属性怎么来的初值_设置Mysql表只读,关键时刻或许能救你一命
  7. 数据结构与算法分析c++第四版_数据结构与算法 - 时空复杂度分析
  8. python一个中文占几个字节_python中英文字母和中文汉字所占的字节
  9. Vue指令(二)--数组的变动
  10. 《21天学通C语言(第7版)》一6.4 小 结
  11. SQL数据库的存错过程中output用法
  12. Java模拟醉汉行走问题_醉汉随机行走问题的统计学模型.pdf
  13. ibm java虚拟机_IBM J9 Java虚拟机正式开源,贡献给Eclipse基金会管理
  14. dataframe一列拆分成多列
  15. kudu教程(一)——简介
  16. 并发编程-并发编程的挑战
  17. synchronized,ReentrantLock、ReentrantReadWriteLock和StampedLock
  18. 远程网络教学系统--UML图
  19. 64位安卓* 和安卓运行库
  20. 【漫事杂谈007】哈利波特电影一共有几部

热门文章

  1. flutter中TextField光标偏移处理
  2. 浅谈java15新特性
  3. 计算机运行缓慢的原因,电脑运行很慢是什么原因?怎么解决?
  4. 黑客入门教程(非常详细)从零基础入门到精通
  5. 前端面试题(自用,仅供参考)
  6. 基于node.js和vue的前后端分离影院售票系统电影院影片管理
  7. 计算机软件板块估值,计算机行业投资策略:估值水平渐趋合理 孕育新机会
  8. 扑克憋七怎么玩?憋七游戏打法介绍
  9. 国瀚实业|轻松理财只需做好这五件事
  10. AJAX控件使用教程