浅谈 HTTP协议

HTTP协议

HTTP(超文本传输协议,HyperText Transfer Protocol) 是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件都必须遵守这个标准。

设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。是用于从 WWW 服务器传输超文本到本地浏览器的传输协议。

默认使用 80 端口,HTTP 客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的 TCP 连接。

HTTP协议和 TCP协议是不冲突的,HTTP 定义在七层协议中的应用层,TCP 解决的是传输层的逻辑。

版本

HTTP1.0 是第一个在通讯中指定版本号的 HTTP 协议版本,至今仍被广泛采用,特别是在代理服务器中。

HTTP1.1是当前版本,持久连接被默认采用,并能很好地配合代理服务器工作,还支持以管道方式同时发送多个请求,以便降低线路负载,提高传输速度。

HTTP2.0 在 HTTP1.x 的基础上,大幅度的提高了 Web 性能,减少了网络延迟。

HTTP1.0 和 1.1 在之后很长的一段时间内会一直并存,这是由于网络基础设施更新缓慢所决定的。

HTTP 1.0

HTTP1.0 是 HTTP 协议老的标准,其为了提高系统系统的效率,规定浏览器与服务器只保持短暂的连接,浏览器每一次请求都需要与服务器建立一个 TCP 连接。

TCP 协议提供传输控制,按顺序组织数据,和错误纠正。HTTP 协议的瓶颈和优化都是基于 TCP 协议本身的。如 TCP 建立连接时需要三次握手,三次握手有 1.5 个 RTT(Round-Trip-Time)的延迟,TCP 在建立初期还有慢启动(Slow Start)的特性,所有连接的重用总是比新建连接性能要好。

HTTP1.0 支持长连接,需要设置 Connection: keep-alive参数来告诉服务器端要建立一个长连接。

HTTP1.0 在请求方式新增了POST,DELETE,PUT,HEADER等方式

增添了请求头和响应头的概念,在通信中指定了 HTTP 协议版本号,以及其他的一些元信息 (比如: 状态码、权限、缓存、内容编码)

扩充了传输内容格式,图片、音视频资源、二进制等都可以进行传输

在这个版本主要的就是对请求和响应的元信息进行了扩展,客户端和服务端有更多的获取当前请求的所有信息,进而更好更快的处理请求相关内容。

HTTP 1.0 特性:

  • 无状态:服务器不跟踪不记录请求过程的状态
  • 无连接:浏览器每次请求都需要建立 TCP 连接

对于「无状态」的特性可以借助 cookie/session 机制来做身认证和状态记录

无连接则导致性能缺陷:

  1. 无法复用连接

    每次发送请求都需要一次 TCP 连接 (3次握手,4次挥手),使网路的传输效率非常低

  2. 队头堵塞

    HTTP1.0 规定在前一个请求响应到达之后,下一个请求才能发送。如果前一个阻塞,后面的请求也阻塞

HTTP 1.1

1.1 是 1.0 发布之后半年就推出的版本。为了解决传输效率的问题,1.1完善 1.0 版本。

HTTP 1.1 默认支持长连接(持久连接)无需手动设置 Connection: keep-alive,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。

基于上面的长连接基础,HTTP1.1 还引入了管道机制(Pipelining)。管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回

HTTP1.1 的默认模式是使用管道机制的长连接。

在 HTTP1.1 中默认允许Connection: keep-alive 但是在一个 TCP 连接里面数据通信是按次序进行的,服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为”队头堵塞”(Head-of-line blocking)。

HTTP1.1 特性:

  • 基于管道化的长连接

    默认支持管道化的长连接,无需设置请求头Connection: keep-alive 。可以不等第一请求响应,继续发送请求。但是响应的顺序还是按照请求的顺序返回,第一个响应如果阻塞后面请求的响应也一样阻塞。队头堵塞的问题依然没有得到解决

  • 缓存处理

    新增加字段 cache-control

    当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求。

  • 支持断点续传

    在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率

HTTP 2.0

HTTP2.0 比之前的协议在性能上有很大的提升。

HTTP2.0 协议拥有了新的特性:

多路复用 (Multiplexing)

多路复用允许同时通过单一的 HTTP2.0 连接发起多重的 请求-响应 消息。

在 HTTP1.1 协议中浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞。

HTTP2.0 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上双向交换消息。

帧(frame)和流(stream)是 HTTP2.0 中两个很重要的概念:

帧代表着最小的数据单位,每个帧都会标识出该帧属于哪个流,流就是由多个帧组成的数据流。

多路复用,也就是在一个 TCP 连接中可以存在多条流,就是我们所说的可以发送多个请求,对端可以通过帧的标示知道,该帧属于哪个流(请求),通过这个技术及意义避免 HTTP 1.x 中的队头阻塞问题,极大的提高传输性能。

二进制分帧

HTTP1.x 的解析是基于文本,HTTP2.0 之后将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,提高传输效率

HTTP2.0 在 应用层 (HTTP2.0) 和传输层 (TCP or UDP) 之间增加一个二进制分帧层。在不改动 HTTP1.x 的语义、方法、状态码、URI 以及首部字段的情况下, 解决了HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量。

HTTP2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。

首部压缩(Header Compression)

由于 HTTP 是无状态的,每一个请求都需要头部信息标识这次请求相关信息,所以会造成传输很多重复的信息,当请求数量增大的时候,消耗的资源就会慢慢积累上去。

HTTP1.1并不支持 HTTP 首部压缩, HTTP2.0 使用了专门为首部压缩而设计的 HPACK 算法。

HTTP2.0 可以维护一个头部信息字典,差量进行更新头信息,减少头部信息传输占用的资源

服务端推送(Server Push)

HTTP2.0 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送

服务端推送是一种在客户端请求之前发送数据的机制。

在 HTTP2.0 中,服务器可以对客户端的一个请求发送多个响应。服务器可以额外的向客户端推送资源,而无需客户端明确的请求

当我们对支持 HTTP2.0 的服务器请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。

HTTPS

HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输隐私信息非常不安全。

为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对 HTTP 协议传输的数据进行加密,从而就诞生了HTTPS。

HTTPS 在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。

TLS/SSL 协议不仅仅是一套加密传输的协议,TLS/SSL 中使用了非对称加密,对称加密以及 HASH 算法。

握手过程的简单描述如下:

  1. 浏览器将自己支持的一套加密规则发送给网站。

  2. 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。

    证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息

  3. 获得网站证书之后浏览器要做以下工作:

    1. 验证证书的合法性
    2. 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密
    3. 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站
  4. 网站接收浏览器发来的数据之后要做以下的操作:

    1. 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证 HASH 是否与浏览器发来的一致
    2. 使用密码加密一段握手消息,发送给浏览器
  5. 浏览器解密并计算握手消息的 HASH,如果与服务端发来的 HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据。

TLS 握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。

正是由于 HTTPS 非常的安全,攻击者无法从中找到下手的地方,于是更多的是采用了假证书的手法来欺骗客户端,从而获取明文的信息。默认 HTTP 的端口号为 80,HTTPS 的端口号为 443。

HTTPS 和 HTTP 对比

  • HTTPS 协议需要申请证书
  • HTTP 和 HTTPS 使用端口不一样,前者是80,后者是443
  • HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,HTTPS 行在 SSL/TLS 之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的
  • HTTPS 可以有效的防止运营商劫持

HTTPS 握手过程

一、Client → Server

Client Hello

握手开始时,总是由先客户端会发送 Client Hello 信息给服务端,主要包含

  • Version Number 客户端支持的协议版本
  • Randomly Generated Data 32 字节长度的随机值,用于之后生成主密钥。
  • Session Identification Session ID,第一次连接时为空。
  • Cipher Suite 客户端支持的加密算法列表,按优先级顺序排列。

二、Server → Client

Server Hello

接着,服务端收到客户端发来的消息之后,会返回 Server Hello 信息给客户端,告知客户端接下来使用的一些参数

  • Version Number 通信协议版本
  • Randomly Generated Data 32 字节长度的随机值,用于之后生成主密钥
  • Session Identification Session ID
  • Cipher Suite 加密算法

Server Certificate 证书

服务端还会带上证书返回给客户端。证书中含有服务端的公钥、网站地址、证书的颁发机构等信息。

客户端收到服务端返回的证书之后,会验证该证书的真实合法性。

Server Key Exchange 额外数据

这个是可选的,取决于使用的加密算法。主要是携带密钥交换的额外数据。

Server Hello Done

表示服务端已经发送完毕,并等待客户端回应。

三、Client → Server

Client Key Exchange

客户端使用之前发送给服务端及服务端返回的随机数,生成预主密钥,然后用服务端返回的公钥进行加密。

Change Cipher Spec

告诉服务端,之后的所有信息都会使用协商好的密钥和算法加密

Client Finished

客户端的握手工作已经完成。这条信息是握手过程中所有消息的散列值。

四、Server → Client

Change Cipher Spec Message

告知客户端,会使用刚刚协商的密钥来加密信息

Server Finished Message

表示服务端的握手工作已经完成

数字证书申请流程

  1. 网站提交身份信息给CA机构
  2. CA机构审核信息的真实性
  3. 对信息进行Hash,计算信息摘要
  4. CA机构的密钥加密信息摘要,得到数字签名

浏览器验证证书

  1. 浏览器利用证书的原始信息计算得到信息摘要
  2. 利用CA的公钥解密数字证书中的数字签名,解密出来的数据也是信息摘要
  3. 比较两个摘要是否相等

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!