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

证书信任的过程:

证书的信任是通过代理的方式进行信任(NSURLConnection和NSURLSession两种方式进行信任)

客户端信任证书的过程:

1.当客户端要访问服务器的时候,服务器向客户端发送受保护的信任证书

2.客户端判断是否对客户端发送的证书进行信任,,

3.如果信任.则客户端会安装公钥在客户端,而服务器就拥有受保护证书的密钥,每一次向服务器请求数据的时候,服务器会先将要发送的数据进行密钥加密,客户端对所传数据通过公钥解密

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

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

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

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

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

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

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

// 原因:没有信任证书

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

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

@property (nonatomic, strong) NSURLSession *session;
- (NSURLSession *)session {if (_session == nil) {NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];}return _session;
}

2.发起数据任务

 // urlNSURL *url = [NSURL URLWithString:@"https://域名"];// 发起数据任务[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {NSLog(@"%@---%@",response,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);}] resume];

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

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challengecompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {/*<NSURLProtectionSpace: 0x7fef2b686e20>: Host:mail.itcast.cn, Server:https, Auth-Scheme:NSURLAuthenticationMethodServerTrust,*/// 判断是否是信任服务器证书if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {// 告诉服务器,客户端信任证书// 创建凭据对象NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];// 通过completionHandler告诉服务器信任证书completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);}NSLog(@"protectionSpace = %@",challenge.protectionSpace);
}

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

1.发送请求:

    // urlNSURL *url = [NSURL URLWithString:@"https://mail.itcast.cn"];// requestNSURLRequest *request = [NSURLRequest requestWithURL:url];// 发送请求[NSURLConnection connectionWithRequest:request delegate:self];

2.信任证书

#pragma mark - NSURLConnectionDataDelegate 代理方法
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {// 判断是否是信任服务器证书if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {// 告诉服务器,客户端信任证书// 创建凭据对象NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];// 告诉服务器信任证书[challenge.sender useCredential:credntial forAuthenticationChallenge:challenge];}
}

3.获取请求到的数据

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {NSLog(@"data = %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}

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

先上代码:

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];manager.securityPolicy.validatesDomainName = NO;manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil];[manager GET:@"https://域名" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {NSLog(@"%@",downloadProgress);} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {NSLog(@"%@---%@",[responseObject class],responseObject);NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"%@",error);}];

注意解释遇到的坑:

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/

取得安全凭证

1. 确认有使用安全连线

如果你跟远端伺服器是透过 HTTP 连线,那就不是安全连线,如果是 HTTPS 那就是安全连线。

2. 准备好网站的安全凭证

接下来我们需要凭证档(Certification file),它的副档名是 .cer,你可以跟你们的网站管理员询问,通常他们都知道怎麽拿到这个档桉。

如果你的网站管理员没有 .cer 档,只有 .crt 档,那你可以透过以下这行指令转档,要注意的是它是採用 DER 编码格式(请自行将 myWebsite 替换成你想要的名字):

openssl x509 -in myWebsite.crt -out myWebsite.cer -outform der

如果很不幸的,你的网站管理员连 .crt 档都没有,那你也可以使用下列这一整行指令从你们的网站取得凭证(请自行将 www.mywebsite.com 替换成你们的网址):

openssl s_client -connect www.mywebsite.com:443 </dev/null 2>/dev/null | openssl x509 -outform DER > myWebsite.cer

现在你有一个凭证档了。

3. 将凭证加入你的专桉

将你的凭证拖拉放到 Xcode 专桉底下,记得要把 Copy items if needed 跟 Add to targets 打勾

https信任证书的三种方式相关推荐

  1. https信任证书的三种方

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

  2. java获取小程序中用户的unionId的三种方式

    前提条件: 想要获取unionId,必须几个小程序或者公众号在同一个主体之下,要不然没有unionId,只会生成用户的openid,可登陆下面这个微信官方平台查看 https://open.weixi ...

  3. 三种方式实现web站点安全

    因为apache底层走的是tcp协议,而tcp协议是明文的,当你访问一些购物网站或银行网站办理业务时就非常不安全,因为是明文传递,容易被人抓包.为了实现apache站点安全,一般采用身份验证.来源控制 ...

  4. IOS应用分发的三种方式

    IOS应用分发的三种方式 IOS应用分发三种方式 上架到AppStore 扫码或者点击链接下载安装 放到第三方应用内测分发平台 上架到AppStore 这个就不讲了,一句两句讲不清楚,网上教程一大堆, ...

  5. 命令行运行Python脚本时传入参数的三种方式

    三种常用的方式 如果在运行python脚本时需要传入一些参数,例如gpus与batch_size,可以使用如下三种方式. python script.py 0,1,2 10 python script ...

  6. sass文件编译的三种方式【舒】

    [舒:]sass文件编译的三种方式 方式一: 1.webstorm打开evtGulp项目或者mcake-activity项目 2.中,开启gulp->default/develop,启动watc ...

  7. vue 函数 路由跳转_vue中通过路由跳转的三种方式

    router-view 实现路由内容的地方,引入组件时写到需要引入的地方 需要注意的是,使用vue-router控制路由则必须router-view作为容器. 通过路由跳转的三种方式 1.router ...

  8. linux+Qt 下利用D-Bus进行进程间高效通信的三种方式

    linux+Qt 下利用D-Bus进行进程间高效通信的三种方式 原文链接: https://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html ...

  9. discard connection丢失数据_python kafka 生产者发送数据的三种方式

    python kafka 生产者发送数据的三种方式 发送方式 同步发送 发送数据耗时最长 有发送数据的状态,不会丢失数据,数据可靠性高 以同步的方式发送消息时,一条一条的发送,对每条消息返回的结果判断 ...

最新文章

  1. 极客新闻——09、如何打造核心骨干团队
  2. 软件研发之道——有关软件的思考
  3. winhex使用经验
  4. webpack 环境安装
  5. 十年经验工程师为何被裁?
  6. 如何完善自己的知识结构
  7. 2017(深圳) .NET技术分享交流会(第二期)网络直播活动
  8. 拖动卡顿_四招教你解决PS软件卡顿问题!
  9. coloros11跟Android,安卓10与安卓11究竟差异在哪里?我们拿这两台新机试了一下
  10. 如何读出烧录程序.bin的数据_如何改变程序搜索数据的方式?使用Redis进行搜索...
  11. ELDD Chapter 2..3 Linux Kernel Facilities
  12. 双线性对在密码学中的应用(下)
  13. SQLite数据库的CRUD操作
  14. 微软产品下载地址。MSDN 我告诉你。
  15. python爬虫面试题集锦及答案
  16. LTE系统信息(1)-MIB
  17. 机器人简化图画手绘图_机器人简笔画画法图片欣赏
  18. 【高德地图进阶】--- 添加城市版块纹理
  19. python找完数 pta_PTA——完全数
  20. 听了老同志的教导:\r \n 到底是什么

热门文章

  1. 如何实现ArrayList的线程安全
  2. 如何向icloud上传文件_怎么把文件放进苹果icloud
  3. python:shape和reshape函数基本讲解
  4. [MySQL]初始JDBC编程
  5. 【Maven】项目打包-war包-Jar包[IDEA将项目打成war包]
  6. Altium Designer 入门
  7. win10 + Ubuntu 20.04 LTS 双系统安装 (UEFI + GPT)(图文,多图预警)
  8. 【Windows】win10任务栏图标空白的解决方案
  9. Allegro Shape菜单详解
  10. 怎样在Word文档中插入GIF动画