前言
据我个人了解,很多工作很久的开发者对HTTP的理解非常的片面甚至有些偏差,经常把HTTP和TCP混淆,所以我认为我有必要将这两个概念进行澄清,前两篇文章我们描述了传输层协议TCP、UDP以及对应的Socket编程,从这篇文章我们开始转战应用层,我将会连续推出关于应用层的几篇文章,包括应用层协议HTTP、HTTPS以及基于HTTP的网络请求框架的使用和源码解析。
1 HTTP
1.1 HTTP概述
HTTP全称是HyperText Transfer Protocol,译成中文是超文本传输协议
,当时理解这个命名的时候我是有点崩溃的,这也是为什么很多开发者将TCP和HTTP进行混淆的原因,HTTP不是应用层协议吗?干嘛说它是超文本传输
协议,其实我个人认为这个命名是真的有点误导人,简单说它就是基于TCP的应用层协议,HTTP负责把数据按照协议进行封装然后由TCP进行传输,HTTP严谨的译名应该是超文本转移协议
,命名就是这么回事,那HTTP的作用到底是什么呢?前面我们也说了,HTTP是完全基于TCP进行传输的,TCP是面向字节流的传输协议,接收方收到的全是字节,所以说如果发送方和接受方不约定一套协议解析这些字节,即使接收方收到数据那么他也看不懂,而HTTP就属于双方约定的这种协议,Client和Server必须同时严格遵守。
我这描述的够白话了吧 (゜-゜),相信聪明的你肯定能理解HTTP存在的意义以及与TCP的区别,另外,应用层协议并不只有HTTP,好有很多,比如:FTP、SMTP等等。
1.2 HTTP报文
HTTP报文分为请求报文
和响应报文
请求报文
请求报文可分为三大部分,分别是报文首部、空行、报文主体。而报文首部又可细分为两部分,分别是请求行、请求头字段,我绘制了一张草图来表示HTTP请求报文,如图1-1
里面一些专业的词汇我会在文章后面详细讲解,在此大家只需要了解HTTP报文结构即可
- 请求行:包含三部分内容,请求方法、Uri路径、HTTP版本
- 请求头字段:头字段可以为0个或多个
- 空行:换行符(CR+LF),用于区分报文首部和报文主体
- 主体:需要发送的数据
报文第一行是请求行,位于空行和请求行之间为请求头字段,空行后面为请求主体。
请求报文实际结构如图1-2,该图摘自这篇文章
响应报文
请求报文也分为三大部分,分别是报文首部、空行、报文主体。而报文首部也可细分为两部分,分别是状态行、响应头字段,结构和请求报文基本相同所以就不再用图来表示(画图是真的费劲- -)。
- 状态行:包含三部分内容,HTTP版本、状态码、描述信息
- 响应头字段:头字段可以为0个或多个
- 空行:换行符(CR+LF),用于区分报文首部和报文主体
- 主体:需要响应的数据
报文第一行是状态行,位于空行和状态行之间为响应头字段,空行后面为响应主体
1.3 HTTP头字段
上满我们讲到HTTP报文分为首部和实体,首部又可分为请求/状态行和头字段,请求/状态行就是一些HTTP版本请求方法之类的只占用一行,而头字段可以为0个或多个。
头字段由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔,是用来封装请求或响应一些基本信息,下满我列举一些比较常见的头字段:
Accept:客户端可接受的MIME类型。
Accept-Charset:客户端可接受的字符集。
Accept-Encoding:客户端能够进行解码的数据编码方式,比如gzip。
Accept-Language:客户端所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
Connection:允许客户端和服务器指定请求/响应连接有关的选项。
Content-Length:表示请求消息正文的长度。
Cookie:设置cookie,这是最重要的请求头信息之一
From:请求发送者的email地址,由一些特殊的客户端程序使用
HTTP头字段有很多个,就不一一列举,感兴趣的同学可自行了解。同时头字段也可分为请求头字段、响应头字段、通用头字段、实体头字段。
1.4 HTTP状态码
状态码是客户端对服务器进行请求时,服务器用来描述的一个请求结果。通过对状态码的分析,客户端可以获取到请求的一个状况。
状态码分类:
- 1xx:类别为Informational(信息性状态码),代表请求正在处理
- 2xx:代表请求成功,最常见的就是200 OK
- 3xx:代表重定向,提示客户端请求耳朵URI已发生变化
- 4xx:代表客户端错误,提示客户端错误发生在你这
- 5xx:服务器错误,提示客户端错误发生在服务器
状态码这一块没啥难的,基本不用思考就能理解,所以我就不挨个将状态码列举讲解,感兴趣的同学可自行了解。
1.5 HTTP缓存
HTTP每次请求都要建立一个连接同时请求结束后会断开连接,如果连续请求同一资源,需要多次建立和断开连接,这样其实是没必要的,所以HTTP也具备缓存功能,一定程度上提升了请求效率。
HTTP缓存可以大致可分为两种:强制缓存和对比缓存
强制缓存
Expires
:客户端第一次进行请求的时候服务器会返回一个头字段为Expires
的头信息,代表有效日期,客户端要对该日期进行保存,下一次请求该资源的时候会判断当前日期是否超过有效日期,没有就直接从缓存中获取。超过就再次从服务器获取,Expires
日期格式如下:
Expires:Thu, 16 Mar 2018 12:31 GMT
Cache-Control
:通过Expires
进行缓存是存在安全隐患,如果客户端与服务器日期不一致就可能出现BUG,所以在HTTP1.1后推出了另一种缓存策略Cache-Control
来代替Expires
。Cache-Control
有如下几种取值:
private:客户端可以缓存,为默认取值。
public:客户端和代理服务器都可以缓存。
max-age:xxx:缓存内容将在xxx秒后失效,指定了age后默认为private。
no-cache:使用对比缓存来验证缓存数据。
no-store:不进行任何缓存,
Cache-Control
返回格式如下:
Cache-Control: public ,max-age=31536000
在HTTP1.1之前,Expires
和Cache-Control
同时存在时Expires
会覆盖掉Cache-Control
,而在HTTP1.1之后正好与之相反
对比缓存
与强制缓存不同,对比缓存通过服务器来决定是否需要缓存,也就是说需要对服务器进行请求,在这有的同学可能会有疑问:"你都对服务器进行请求了,缓存还有意义吗?",是这样的,如果服务器判断缓存有效只返回一个响应首部不返回响应体,这就好比我背10块砖头上2楼跟背100块砖头上2楼用的时间肯定不一样。下满我们来看一下对比缓存的具体流程:
Last-Modified/If-Modified-Since
:
- Last-Modified:客户端在进行第一次请求的时候服务器会返回一个头字段名称为Last-Modified的日期代表服务器对该资源最后修改时间,客户端需要对该日期进行保存。
- If-Modified-Since:客户端在之后的请求中会在请求头中加入头字段If-Modified-Since,其内容为服务器返回的Last-Modified,服务器收到后会判断缓存是否有效,如果有效返回304告诉客户端从自己本地缓存读取数据,否则返回200并携带新的响应体同时更新Last-Modified,客户端收到响应后重新保存Last-Modified和数据。
Etag/If-None-Match
:
Etag是资源的一个标识,当资源修改后Etag值会改变,Etag是由服务器生成,
Etag/If-None-Match
判断过程和Last-Modified/If-Modified-Since
基本一致,唯一区别是缓存有效即服务器返回304时前者会在响应头中加入Etag
,而后者不会再响应头中加入Last-Modified
.
Last-Modified/If-Modified-Since
和 Etag/If-None-Match
判断方式基本相似那么二者同时存在的意义是什么呢?大概有三点:
- 一些资源可能会周期性的改变,但只是改变时间内容却不变,这种情况很容易错认为内容已经发生改变重新返回数据。
-
Last-Modified/If-Modified-Since
时间单位是精确到秒的,所以无法保证精度在秒之内的的正确性。 - 某些服务器不能精确的得到文件的最后修改时间。
一般来说对比缓存要配合强制缓存使用,Expires
和Cache-Control
优先级最高,其次是Etag/If-None-Match
,最后是Last-Modified/If-Modified-Since
,下面我来用一张图来表示通过对比缓存配合强制缓存实现HTTP缓存的流程,如图1-5
画图真的是能要了我的亲命,该图摘自这篇文章
2 HTTPS
HTTPS全称为Hyper Text Transfer Protocol over Secure Socket Layer(HTTP安全套接字),HTTPS使HTTP传输变得更加安全,下面我罗列几点HTTP存在的安全隐患:
- 窃取:HTTP为明文传输,假如HTTP中存在银行卡及密码,不法分子很容易就能窃取
- 伪装:假如客户端正在与服务器进行通信,不法分子可以从中间伪装成客户端与服务器通信。
- 篡改:假如正在进行网络转账,不法分子可以将收钱的银行卡号篡改为自己的银行卡号。
以上三点就是HTTP面临的主要威胁,而通过HTTPS基本可以避免这三种隐患,HTTPS是如何做到安全传输呢?网络结构本身就很复杂,所以想做到数据不被中间者拦截是不可能的,但是可以对数据进行加密,即使中间者拦截到数据他也看不懂,所以HTTPS是通过对数据各种加密来实现安全传输。
2.1 对称加密
在描述对称加密前我先普及一下加密算法和秘钥的概念,因为有些同学对加密算法和秘钥的概念容易混淆,打个比方,加密算法相当于锁内的构造,而秘钥就相当于钥匙,代码中的体现:
public String encryption(String content0,int key){
...
...
...
return content1;
}
encryption(String content0,int key)就是加密算法,content0是准备加密的内容,key就是秘钥,算法通过key科技将content0加密成别人看不懂的content1.,解密同理。
对称加密:
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。
简单说就是客户的和服务器共享一套算法和秘钥,在传输数据前通过共享秘钥将数据进行加密,然后再进行发送,接收方收到数据后通过共享秘钥对数据进行解析。
优点:简单、直接、效率高。
缺点:秘钥不适合在网络上传输,因为拿到秘钥后一些算法是可能被破解的,所以每个客户端都要有一个唯一的共享秘钥,并且服务器要保存所有客户端的共享秘钥,也增加了服务器的压力。
2.2 非对称加密
我们来看一下非对称加密的官方解释:
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
优点:因为存在公钥和私钥,秘钥可以在网络上传输,所以灵活性较高
缺点:算法复杂度高,所以加密解密耗时较长
实际应用
对称加密和非对称加密都有各自的优缺点,那能不能将二者优点相结合来进行一次安全传输呢?是可以的,下面我来说一下对称加密结合非对称加密额使用流程:
- 客户端请求服务器,服务器返回一个公钥
- 客户端生成一个对称加密秘钥,通过公钥进行加密传给服务器
- 服务器收到对称加密秘钥通过私钥进行解密
经过上面的三步服务器和客户端就可以确定一个秘钥,在此后的传输通过该秘钥进行加解密就可以保证数据不被窃取。这种加密方式就摒除了对称加密密钥不可在网络传输的弊端和非对称加密加密效率低下的问题,实际场景中基本也是通过该方式对数据进行加密。
数字签名
在网络传输中通过数字签名可以保证数据的完整性,具体流程如下:
(假设客户端和服务器已经完成对称加密秘钥的确定)
- 服务器在发送数据前先对数据进行一次hash运算得到一个数值,然后通过秘钥对该数据进行加密
- 客户端收到数据后对数据进行解密,对数据进行hash运算,然后再对服务器生生地hash值进行解密,最后比较两个hash值是否相同,如果不相同证明数据在网络传输中被进行了篡改
2.3 CA认证
CA的全称是Certificate Authority(证书颁发机构),它可以为企业颁发数字证书确认这些企业的身份,同时也可以吊销数字证书。在HTTPS中需要一个SSL证书,该证书也属于数字证书的一种由CA进行颁发,内容包括公钥
+申请者与颁发者信息
+签名
.
具体的证书验证过程:
- 客户端请求服务器
- 服务器将证书和数字签名通过私钥加密携带着公钥一同传递给客户端
- 客户端收到后首先拿着公钥解密证书,拿着证书去CA机构进行认证是否合法
- 如果证书合法就对证书进行hash运算,再将数字签名解密,对比两个hash值,如果一致代表证书没有被冒充。
另外,进行CA认证一般是要收费的
2.4 SSL
重头戏要来了......
SSL全称为Secure Sockets Layer(安全套接层),没错,它就是HTTPS的核心,换句话说就是HTTPS就是HTTP+SSL,通过SSL可以实现HTTP安全传输,实现原理就是基于上面几个小结所讲的对称加密、非对称加密、CA认证,下面我先用一张图来代表SSL整个流程,如图2-1:
我用文字叙述一下整个流程:
- 客户端请求服务器,并携带支持的加密算法
- 服务器选定加密算法,将确认的加密算法+公钥+证书一并返回给客户端
- 客户端收到会拿着公钥去进行CA认证,如果认证成功就生成一个对称秘钥用公钥加密并返回给服务器,否则就视为服务器为非法服务器。
- 服务器拿到对称秘钥后通过私钥进行解密并保存,此后客户端和服务器就可以通过该秘钥对数据进行加密传输
- 服务器发送数据前需要对数据进行一次hash运算得到一个hash值,对数据和hash值加密后传输给客户端
- 客户端收到数据后对数据进行解密,然后对数据进行一次hash运算得到一个hash值,并解密服务器传来的hash值,将两个hash值进行比较,如果不相同可视为数据中途被篡改
以上就是SSL加密流程,SSL实际是位于应用层和传输层之间的,所以SSL并不只属于HTTP,它也可以帮助其他应用层协议实现安全传输。HTTPS内容大概就是这些
总结
本篇文章描述了HTTP和HTTPS,HTTP内容内容相对来说较为简单,都是一些概念性的知识,记住就行了,而HTTPS就是在HTTP和TCP之间加入了SSL,通过SSL可以实现数据安全传输,切记,SSL也可以应用到其他的应用层协议中。本篇文章对HTTP的描述到此为止,下篇文章我将为大家带来《Android网络编程(四)OKHttp使用及封装》