iOS中的HTTPS与AFNetworking

本节主要理解:
1.HTTP1.0和HTTP1.1和HTTP2.0的区别
2.HTTP请求报文头内容
3.https证书校验原理
4.https的加密原理
5.AFNetworking的简介
6.AFNetworking2.0与3.0与4.0的区别
7.中间人攻击的原理,如何预防中间人攻击?

一.http与https的对比

什么是http?

超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。

什么是https?

《图解HTTP》这本书中曾提过HTTPS是身披SSL外壳的HTTP。HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。

1 HTTP1.0和HTTP1.1的区别
1.1 长连接(Persistent Connection)---加快响应速度
HTTP1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。

1.2 节约带宽
HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。

1.3 HOST域
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。

1.4缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。

1.5错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

2 HTTP1.1和HTTP2.0的区别
2.1 多路复用---加快响应速度
HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。

2.2 头部数据压缩---节省带宽
在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。
HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。

2.3 服务器推送
服务端推送是一种在客户端请求之前发送数据的机制。网页使用了许多资源:HTML、样式表、脚本、图片等等。在HTTP1.1中这些资源每一个都必须明确地请求。这是一个很慢的过程。浏览器从获取HTML开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的。
为了改善延迟,HTTP2.0引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。

2.HTTP请求报文头内容
常见的HTTP请求报文头属性
Accept
请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。

Accept:text/plain

Cookie
如上报文头相当于告诉服务端,俺客户端能够接受的响应类型仅为纯文本数据啊,你丫别发其它什么图片啊,视频啊过来,那样我会歇菜的~~~:

客户端的Cookie就是通过这个报文头属性传给服务端的哦!如下所示:
Cookie: $Version=1; Skin=new jsessionid=5F4771183629C9834F8382E23BE13C4C

服务端是怎么知道客户端的多个请求是隶属于一个Session呢?注意到后台的那个jsessionid=5F4771183629C9834F8382E23BE13C4C木有?原来就是通过HTTP请求报文头的Cookie属性的jsessionid的值关联起来的!(当然也可以通过重写URL的方式将会话ID附带在每个URL的后面哦)。

Referer
表示这个请求是从哪个URL过来的,假如你通过google搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是http://www.google.com

Cache-Control

对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。

如以下设置,相当于让服务端将对应请求返回的响应内容不要在客户端缓存:
Cache-Control: no-cache

3.HTTP特点:
1.无状态:协议对客户端没有状态存储,对事物处理没有“记忆”能力,比如访问一个网站需 要反复进行登录操作
2.无连接:HTTP/1.1之前,由于无状态特点,每次请求需要通过TCP三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。
3.基于请求和响应:基本的特性,由客户端发起请求,服务端响应
4 简单快速、灵活
5.通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性
PS:TLS是传输层加密协议,前身是SSL协议,由网景公司1995年发布,有时候两者不区分

HTTPS特点:
内容加密:采用混合加密技术,中间者无法直接查看明文内容
验证身份:通过证书认证客户端访问的是自己的服务器
保护数据完整性:防止传输的内容被中间人冒充或者篡改

二.HTTPS的数据传输

HTTPS采用的是非对称加密+对称加密结合的方式保证数据加密的

图片.png

中文版😂😂😂


图片.png

大概过程
https证书校验原理(简介版)
1.客户端向服务端发其请求,服务端发送证书。
2.客户端本地有内置的证书签发机构对应的公钥,客户端使用公钥解密签名,然后自己计算hash看是否一致。

如果不一致,客户端会进行信任链的验证操作。

重点!!

1)服务器用RSA生成公钥和私钥
2)客户端发起https请求,连接到服务端的443端口
3)服务端将公钥放在证书中传给客户端,私钥自己保存
4)客户端验证证书合法性,验证成功的话,生成一串随机数作为数据传输对称加密的密钥,我们称之为对称密钥
5)然后客户端用公钥对密钥进行加密, 再发给服务器
6)服务端收到客户端发出的数据,使用私钥解密,获取到随机数密钥。即可进行数据传输

三.AFNetworking与HTTPS

1.AFNetworking简介
框架结构

这里分析4.0版本的结构。主要分为五个部分:

1、NSURLSession:网络通信模块,两个文件AFURLSessionManager,AFHTTPSessionManager。AFHTTPSessionManager继承与AFURLSessionManager

2、Reachability 网络状态监听,AFNetworkReachabilityManager

3、Security 网络通讯安全策略模块,AFSecurityPolicy

4、Serialization 序列化,AFURLResponseSerialization,AFURLRequestSerialization

5、UIKit 对于UIKit的扩展库

AFNetworking的请求AFHTTPSessionManager 有一个专门的属性来处理加密策略,AFSecurityPolicy
1.创建一个AFSecurityPolicy

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];

传入参数表示https验证模式,一共三种选项

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    //不验证
    AFSSLPinningModeNone,
    //只验证公钥
    AFSSLPinningModePublicKey,
    //验证证书
    AFSSLPinningModeCertificate,
};

此外AFSecurityPolicy还有三个重要属性

//可以去匹配服务端证书验证的证书
@property (nonatomic, strong, nullable) NSSet <NSData *> *pinnedCertificates;
//是否支持非法的证书(例如自签名证书)
@property (nonatomic, assign) BOOL allowInvalidCertificates;
//是否去验证证书域名是否匹配
@property (nonatomic, assign) BOOL validatesDomainName;

我们项目使用的是机构颁发的证书所以配置比较简单

- (AFSecurityPolicy *)customSecurityPolicy {
    NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"server" ofType:@"p12"]];
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    securityPolicy.allowInvalidCertificates = NO;
    securityPolicy.validatesDomainName = NO;
    securityPolicy.pinnedCertificates = [NSSet.alloc initWithObjects:data, nil];
    return securityPolicy;
}

2.AFNetworking3.0与2.0的区别

最大区别: AFNetworking2.0使用的NSURLConnection,3.0使用的是NSURLSession

1)NSURLConnection下载文件时,先是将整个文件下载到内存,然后再写入到沙盒,如果文件比较大,就会出现内存暴涨的情况。而使用NSURLSessionUploadTask下载文件,会默认下载到沙盒中的tem文件中,不会出现内存暴涨的情况。

2)NSURLConnection停止请求的发送,停止后不能继续访问,需要创建新的请求。NSURLSession有三个控制方法,取消(cancel)、暂停(suspend)、继续(resume),暂停以后可以通过继续恢复当前的请求任务。

3)AFN3.0 NSURLSession 不需要2.0NSURLConnection 的常驻线程。
2.0需要常驻线程是因为请求回调依赖当前线程,而AFN3.0 NSURLSession的请求回调不需要依赖当前线程,可以指定回调的delegateQueue,这样也就不需要再对线程进行保活。

7.中间人攻击的原理,如何预防中间人攻击?
SSL劫持攻击

SSL劫持攻击即SSL证书欺骗攻击,攻击者为了获得HTTPS传输的明文数据,需要先将自己接入到客户端和目标网站之间;在传输过程中伪造服务器的证书,将服务器的公钥替换成自己的公钥,这样,中间人就可以得到明文传输带Key1、Key2和Pre-Master-Key,从而窃取客户端和服务端的通信数据;

但是对于客户端来说,如果中间人伪造了证书,在校验证书过程中会提示证书错误,由用户选择继续操作还是返回,由于大多数用户的安全意识不强,会选择继续操作,此时,中间人就可以获取浏览器和服务器之间的通信数据

图片.png

如何预防中间人攻击?
因为在握手阶段服务端的证书必须返回给客户端,如果客户端在打包的时候,就把服务端证书放到本地,在握手校验证书的环节进行比较,服务端返回的证书和本地内置的证书一模一样,才发起网络请求。否则,直接断开连接,不可用。

参考文章
AFNetworking之于https认证
HTTP和HTTPS协议,看一篇就够了
https原理

over !!

推荐阅读更多精彩内容