首页 HTTP
文章
取消

HTTP

HTTP请求报文格式

QQ截图20220809091212

注意请求体(请求数据)部分GET请求没有。

HTTP请求方法

  1. GET:向指定的资源发出“显示”请求。使用 GET 方法应该只用在读取数据,而不应当被用于产生“副 作用”的操作中,例如在 Web Application 中。其中一个原因是 GET 可能会被爬虫等随意访 问。所以GET请求不应被定义为带有副作用的操作。

  2. HEAD:与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文 部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该 资源的信息”(元信息或称元数据)。(只返回请求头
  3. POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含 在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
  4. PUT:向指定资源位置上传其最新内容。但是鉴于PUT方法自身不带验证机制,任何人都可以上传文件,存在安全性问题,因此一般网站都不采用该方法。
  5. DELETE:请求服务器删除 Request-URI 所标识的资源。同样不带验证机制,存在安全性问题。
  6. TRACE:回显服务器收到的请求,主要用于测试或诊断。
  7. OPTIONS:这个方法可使服务器传回该资源所支持的所有 HTTP 请求方法。用’*‘来代替资源名称, 向 Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作。
  8. CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服 务器的链接(经由非加密的 HTTP 代理服务器)

GET和POST区别

GET 的语义是从服务器获取指定的资源, 而POST 的语义是根据请求负荷(报文body)对指定的资源做出处理(通常导致状态变化或副作用,比如增添或删除数据等)

  • GET一般没有请求体,POST有请求体
  • GET参数通过URL传递,而POST参数会放在请求体中,这导致:
    • 由于URL有长度限制,所以GET的参数长度有限制,POST没有
    • GET参数暴露在URL中,不安全。不可传递敏感信息。这个不安全在传输中因为是HTTPS所以不是很担心,主要担心的是存在在历史记录内。
    • 由于URL只支持ASCII编码,所以GET编码种类受限。
    • 由于URL含有参数,历史记录内会保存GET请求参数,但是POST不会
    • 所以GET的URL可以被当做书签
  • GET请求在浏览器回退的时候是无害的,但是POST会再次提交请求,所以会出现浏览器问你是否要继续
  • GET请求发送的时候,请求行和请求头和请求体是一起发送的。(理解为没有请求体)。然后服务器一并接受并相应。而POST请求发送的时候,会先发送请求行和请求头,服务器响应100 continue后,再次发送请求体。然后服务器响应。

HTTP1.1

优点:

支持长连接

  • 支持长连接,无需每一个请求都对应一次TCP握手和挥手。可以在一个TCP连接中进行多次请求。

QQ截图20220810064353

支持管线化。解决了请求端队头阻塞,但是没有解决响应端的队头阻塞。

  • 支持管线化。意思是客户端发出的请求不必排队发送(也就是前一个请求未响应的时候下一个请求无法发送)。但是服务器必须按照接受请求的顺序返回管线化的请求响应。
    • 举个例子,非管线化就是1发送,1接受,然后2发送,2接受。管线化就是1发送,2发送。但是服务器返回必须也先返回1再返回2。不可乱序返回。
    • 所以HTTP1.1的管线化解决了请求的队头阻塞(可以同时发送多个请求),但是没有解决响应的队头阻塞(服务器必须按照顺序返回,如果第一个阻塞了,后面的就阻塞了)

QQ截图20220810064729

引入了host域名

  • 在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点

新增了几个状态码所以支持:

支持 Range(断点续传)

支持先发送请求头,等服务器确认后返回100再次发送请求体

  • HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,
  • 客户端就可以继续发送带实体的完整请求了。100 (Continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。

缺点:

无状态

  • 意思就是没有记忆能力,如果一个数据依靠其他请求,则每次都需要验证。理解为从登陆到下单,每一个页面都需要知道用户身份,则每一次都要登陆一下。

明文传输

  • 没用HTTPS

请求头和响应头无法压缩,只能压缩请求体和响应体

因为首部信息是JSON的。没有压缩。所以冗长浪费性能

没有请求优先级控制

请求只能由客户端主动发起

HTTP2.0

QQ截图20220810065919

优点:

支持头部压缩

  • HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分
  • 这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

二进制格式

  • HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)

数据流

  • HTTP/2 的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
  • 在 HTTP/2 中每个请求或响应的所有数据包,称为一个数据流(Stream)。每个数据流都标记着一个独一无二的编号(Stream ID),不同 Stream 的帧是可以乱序发送的(因此可以并发不同的 Stream ),因为每个帧的头部会携带 Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息
  • 客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。

因为使用了数据流,所以可以指定数据流的优先级。支持了优先级控制

多路复用 解决了响应端的队头阻塞

HTTP/2 是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应

移除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,大幅度提高了连接的利用率, 解决了响应端的队头阻塞

举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。

QQ截图20220810070205

支持服务器推送

HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务端不再是被动地响应,可以主动向客户端发送消息。

比如,客户端通过 HTTP/1.1 请求从服务器那获取到了 HTML 文件,而 HTML 可能还需要依赖 CSS 来渲染页面,这时客户端还要再发起获取 CSS 文件的请求,需要两次消息往返,如下图左边部分:QQ截图20220810070402

如上图右边部分,在 HTTP/2 中,客户端在访问 HTML 时,服务器可以直接主动推送 CSS 文件,减少了消息传递的次数。

缺点:

虽然解决了HTTP层面的发送队头阻塞和响应队头阻塞,但是有TCP层面的队头阻塞

HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。QQ截图20220810070455

HTTPS

HTTP 与 HTTPS 有哪些区别?

  1. HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
  2. HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
  3. HTTP 的端口号是 80,HTTPS 的端口号是 443。
  4. HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTPS 解决了 HTTP 的哪些问题?

HTTP 由于是明文传输,所以安全上存在以下三个风险:

  • 窃听风险,比如通信链路上可以获取通信内容,用户号容易没。
  • 篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。
  • 冒充风险,比如冒充淘宝网站,用户钱容易没。

HTTPS 优点:

  • 安全性高(废话),不存在窃听,篡改和冒充风险

HTTPS缺点:

  • 延迟较高,因为TCP握手后还需要进行SSL握手。
  • 部署成本高,需要进行加密计算,部署证书等。

HTTPS是怎么解决风险的?

HTTPS采用了混合加密 和 摘要算法来解决风险

  • 混合加密的方式实现信息的机密性,解决了窃听的风险。
  • 摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
  • 将服务器公钥放入到数字证书中,解决了冒充的风险。

混合加密

HTTPS 采用的是对称加密非对称加密结合的「混合加密」方式:

  • 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。

采用「混合加密」的方式的原因:

  • 对称加密只使用一个密钥,运算速度快,但是密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

摘要算法+数字签名

摘要就是他妈的哈希。服务器把数据和哈希值一起发出去,然后客户端拿到数据后再算一遍哈希值,如果和服务器发来的一样,能说明数据没有被篡改。但是你没办法确认这个数据真的是服务器发的。有可能是别人发的。就是中间人攻击。所以我们会有一个数字证书。

  • 服务器把自己的公钥注册到CA,CA用自己的私钥给服务器的公钥签名,然后颁发数字证书。数字证书包含着服务器的公钥。CA的公钥是预先保存在浏览器或操作系统内的。所以客户端收到了数字证书后,用CA的公钥给CA私钥加密的数字证书解密(公钥解密,私钥加密证明不会被冒充)。这就证明了这个证书确实是CA颁发的。所以也就知道了这个数字证书里面的服务器公钥确实是服务器的。

公钥和私钥 (非对称加密)

  • 公钥,这个是可以公开给所有人的;
  • 私钥,这个必须由本人管理,不可泄露。

这两个密钥可以双向加解密的,比如可以用公钥加密内容,然后用私钥解密,也可以用私钥加密内容,公钥解密内容。

流程的不同,意味着目的也不相同:

  • 公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;
  • 私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。

HTTPS建立流程:

一句话版本:先TCP三次握手,然后TLS四次握手。所以HTTPS首次通信是握手7次

unknown

SSL/TLS 协议建立的详细流程:

1. ClientHello

首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。

在这一步,客户端主要向服务器发送以下信息,是明文传输的

(1)客户端支持的 SSL/TLS 协议版本,如 TLS 1.2 版本。

(2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。

(3)客户端支持的密码套件列表,如 RSA 加密算法。

2. SeverHello

服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:

(1)确认 SSL/ TLS 协议版本,如果浏览器不支持,则关闭加密通信。

(2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。

(3)确认的密码套件列表,如 RSA 加密算法。

(4)服务器的数字证书。

3.客户端回应

客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。

如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:

(1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。

(2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。

(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。

上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。

服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。因为客户端随机数+服务器随机数+pre-master和加密算法都是协商好一样的,所以会话秘钥也是一样的,所以开始对称加密

4. 服务器的最后回应

服务器收到客户端的第三个随机数(pre-master key)之后,通过服务器的私钥解密,拿到pre-master key。然后计算出本次通信的「会话秘钥」。

然后,向客户端发送最后的信息:

(1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。

(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

至此,整个 SSL/TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。

总结:

TCP三次握手后,开始TLS四次握手。

  1. 客户端发送:客户端随机数,客户端TLS版本,和支持的加密协议。
  2. 服务器发送:服务器随机数,确认的TLS版本,确认的加密协议和服务器证书
    • 客户端通过证书验证身份后,拿到服务器公钥。然后生成一个pre-master key。此时客户端可以用客户端随机数+服务器随机数+pre-master key生成会话秘钥。
  3. 客户端发送:被服务器公钥加密过的pre-master key, 加密算法改变通知和客户端握手结束通知
    • 服务器端通过私钥解密拿到pre-master key。此时服务器也可以用客户端随机数+服务器随机数+pre-master key生成会话秘钥。
  4. 服务器发送:加密算法改变通知,服务器握手结束通知

杂项问题:

HTTPS会加密URL吗 – 会

因为 URL 的信息都是保存在 HTTP Header 中的,而 HTTPS 是会对 HTTP Header + HTTP Body 整个加密的,所以 URL 自然是会被加密的。

QQ截图20220814072853

那么HTTPS可以看到域名吗? – 可以

TLS 第一次握手的 “Client Hello” 消息中,有个 server name 字段,它就是请求的域名地址。

关闭keepalive

keepalive必须双方都开启才会生效,只要一方不开启就不生效。

但是是双方哪方先收到Connection: Close 则由收到方关闭。

比如服务器关闭keepalive,那么写回的请求就是 Connection: Close。浏览器接收到这个后就会调用close发送FIN包关闭连接

本文由作者按照 CC BY 4.0 进行授权