HTTP篇

HTTP篇

追随HTTP的发展与演变,由浅入深的学习和理解HTTP

HTTP基本概念

  1. HTTP是什么?

HTTP 是超文本传输协议,全称 HyperText Transfer Protocol.

  • 超文本:超越了普通的文本的文本,包含文字、图片、视频等的混合体。最关键的超链接:从一个超文本跳转到另一个超文本。
  • 传输:两点之间数据的传输,HTTP是双向协议(即双方都需要遵守的),且只要中间人同样遵守HTTP协议,就能实现数据的传递。
  • 协议:HTTP是一个应用于计算机世界里的协议,利用计算机的语言确立了计算机之间(两个以上的参与者)交流通信的规范,并通过相关的控制和错误处理方式来实现计算机的行为约定和规范。

小结:HTTP是一个在计算机世界里在两点之间传输文字、图片、音视频、超链接等超文本数据约定和规范

  1. HTTP常见状态码:

http状态码

  • 200 OK :成功状态码
  • 204 Not Content :响应头没有body的成功状态码
  • 206 Partial Content :表示相应返回body数据并不是资源全部,也是服务器处理成功的状态
  • 301 Moved Permanently :表示永久重定向,说明请求资源已经不存在了,需改用新的URL再次访问。
  • 302 Found :临时重定向,请求的资源还在,暂时需要用另一个URL来访问
    ** 注意:301、302都会在响应头里使用字段Location,指明后续要跳转的URL,浏览器会自动重定向新的URL。**
  • 304 Not Modified :表示资源未修改,直接重定向已存在的缓冲文件,即缓存重定向(不具有跳转的含义)。
  • 400 Bad Request:表示客户端请求的报文有错误,但只是个笼统的错误。
  • 403 Forbidden :表示服务器禁止访问资源,并不是客户端的请求出错。
  • 404 Not Found :表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
  • 500 Internal Server Error :服务器端发生了错误,笼统的错误码。
  • 501 Not Implemented :表示客户端请求功能还不支持,类似“即将开业,敬请期待”
  • 502 Bad Gateway :通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误(例如nginx正常工作,tomcat相应异常)。
  • 503 Service Unavailable :表示服务器忙
  1. HTTP常见字段:

http请求字段

Host 字段:客户端发送请求时,指定服务器的域名。

Content-Length 字段:表明本次回应的数据长度(这里没有是因为是get请求,没有数据)。

粘包问题
背景:HTTP协议是基于TCP传输协议进行通信的,而使用TCP传输协议,就会存在粘包问题。
问题描述:多个应用层的消息在 TCP 层被合并成一个字节流一起发送,接收端读取时无法区分每个消息的边界。
例如:
客户端发送的数据:hello worldhello jackhello alice
在基于TCP传输时,这些消息有可能被合并成一个字节流一起发送。
服务器端连续收到的内容:hello worldhello jackhello alice,接受方不知道从哪里截断每条信息,这个现象就是粘包。
解决:

  • 固定长度的消息
  • 特殊字符作为边界
  • 自定义消息结构

HTTP协议通过设置回车符、换行符作为 HTTP header 的边界,通过 Content-Length 字段作为HTTP body 的边界,这两个方式都是为了解决“粘包”问题。

Connection 字段 :通常用于客户端要求服务器使用HTTP 长连接机制(长连接的特点是:只要任意一端没有明确提出断开连接,则保持TCP连接状态)。
HTTP/1.1 版本默认连接是长连接,但为了兼容老版本的http,需要指定Connection 首部字段的值为 Keep-Alive
注意区分 TCP 的 Keepalive 和 HTTP 的 Keep-Alive。

Content-Type 字段:表示服务器回应时,告诉客户端,本次数据是什么格式。
Accept 字段:客户端请求时,声明自己可以接受哪些数据格式。

Content-Encoding 字段:表示服务器返回的数据的压缩方式。
Accept-Encoding:客户端在请求时,说明自己可以接受哪些压缩方法。

GET与POST

  1. get 与 post 的区别
  • get 的语义是从服务器获取指定的资源,请求参数只允许ASCII 字符,放在URL中。
  • post 的语义是根据请求负荷(报文body)对指定的资源做出处理,携带的数据位于报文body中,可以是任意格式(客户端与服务器协商一致即可)
  1. 安全和幂等
    概念:
  • 安全,在HTTP协议中指请求方法不会“破坏”服务器上的资源。
  • 幂等,指多次执行相同操作,结果都是相同的。
    GET与POST:
  • get 是安全且幂等的,它只做读操作。所以,可以对get请求的数据做缓存,这个缓存可以存到浏览器本身上(彻底避免浏览器发送请求),也可以做到代理上(nginx),而且在浏览器中get请求可以保存作为书签。
    资源过期或数据不一致的解决:
    • 缓存验证机制:浏览器缓存资源后,下次请求并不一定直接使用缓存,先询问服务器“缓存是否还有效”。
    • 设置合理的强缓存:资源访问频繁则设置长时间缓存,反之设置短时间缓存或者禁用强缓存。
    • 文件名加 hash,更新就换文件名(前端最常用)。
    • 重要数据用post、websocket、ajax等方式动态请求
  • post 是新增或提交数据的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据会创建多个资源,同样也不是幂等的。所以,浏览器一般不会缓存post请求,也不能把post请求保存为书签。
  1. 注意:
  • 如果安全是指信息是否会泄露的话,那么get与post数据都不安全,get的数据是直接在浏览器地址栏就可以看到。同样地,post的数据也是明文,虽然地址栏看不到,但是只要抓个包,查看body的数据就可以看到了。所以,要避免传输过程数据被窃取,就要使用HTTPS协议。
  • get请求同样可以带body,post请求的url中也可以有参数,只是规范,不是必须。

HTTP缓存技术

  1. HTTP缓存的实现方式
    HTTP缓存:对于幂等的HTTP请求,把这对请求-响应的数据缓存在本地,下次就直接读取本地的数据,不必通过网络获取服务器的响应了。
    HTTP通过强制缓存与协商缓存实现缓存。

  2. 强制缓存:
    浏览器对缓存是否过期进行判断,决定是否使用缓存的主动性在浏览器这边。
    这里的自service worker 就是使用了强制缓存。

浏览器缓存

强制缓存通过下面两个HTTP响应头部字段实现的,用来表示资源在客户端缓存的有效期:

  • Cache-Control,是一个相对时间
  • Expires,是一个绝对时间
    如果同时拥有这两个字段,Cache-Control 优先级高于 Expires。
    Cache-Control 的使用:
  • 浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小
  • 浏览器再次请求访问服务器中该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间来判断该资源是否过期,如果没有,则直接使用,否则重新请求服务器
  • 如果过期,发送请求到服务器,服务器收到请求后,会再次更新 Response 头部的 Cache-Control
  1. 协商缓存
    服务器端告诉客户端是否可以使用缓存的方式称为协商缓存。

协商缓存

协商缓存的实现:

  • 请求头部中的If-Modified-Size字段与响应头部中的Last-Modified字段实现,这两个字段的意思是:

    • 响应头部中的Last-Modified:标识这个响应资源的最后修改时间
    • 请求头部中的If-Modified-Size:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求,同时带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Size 则与被请求资源的最后修改时间对比,如果最后修改时间较新,说明资源右改动过了,则返回最新资源,HTTP 200 OK;否则,响应 304 走缓存。
  • 请求头部中的 If-None-Match字段与响应头部中的ETag字段,这两个字段的意思是:

    • 响应头部中ETag:唯一标识响应资源
    • 请求头部中的If-None-Match:资源过期时,浏览器发现响应头里头Etag,则再次向服务器发起请求,同时会将请求头 If-None-Match 的值设置为 Etag 的值。服务器收到请求后对比唯一标识 Etag,返回相应的304或200。

小结:第一种实现方式是基于时间实现的,第二种则是基于唯一标识实现的,相对来说后者更加可靠。
注意:两种方式同时出现时,优先判断 Etag ,Etag变了则直接返回新资源,否则再判断Last-Modified。
为什么 Etag 优先级更高?
因为 Etag 能解决 Last-Modified 难以解决的问题:

  • 没有修改文件内容的情况下,最后修改时间也发生了变动
  • 有些文件在秒级以内修改,If-Modified-Since 感知不到
  • 有些服务器不能精确获取文件最后修改时间

注意:协商缓存这两个字段都需要配合强制缓存中的 Cache-Control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。

强制缓存与协商缓存的工作流程

使用ETag字段实现协商缓存的过程:

  • 浏览器第一次访问服务器时,服务器会根据当时的资源生成唯一标识ETag,加在Response头部。
  • 当浏览器再次请求访问服务器时,首先会检查强制缓存是否过期
    • 如果没有过期,直接使用本地缓存
    • 过期了,则把ETag加在请求头部中的if-none-match字段中
  • 服务器再次收到请求后,根据Etag与当前请求资源生成的唯一标识对比
    • 如果相等,则返回 304
    • 不等,则返回 200 并返回资源与 ETag
  • 如果浏览器收到304的请求响应状态码,则直接加载本地缓存,否则更新资源。

HTTP特性

HTTP 常见的版本有 HTTP/1.1,HTTP/2.0,HTTP/3.0,不同版本的 HTTP 特性是不一样的。

  1. HTTP/1.1
  • 优点:简单、灵活和易于扩展、应用广泛和跨平台

    • 简单:报文格式header + body,头部信息也是 key-value简单文本的形式。
    • 灵活和易于扩展:HTTP 协议里的各类请求方法、URL/URI、状态码、头字段等每个组成要求都没有被固定死,允许开发人员自定义和扩充。同时HTTP工作在应用层,则它下层可以随意变化,例如:HTTPS 就是在 HTTP 与 TCP 之间增加了 SSL/TLS 安全传输层;
    • 应用广泛和跨平台
  • 缺点:无状态(双刃剑)、明文传输(双刃剑)、不安全

    • 无状态:不需要记忆HTTP状态,能减轻服务器的负担;同时,由于无状态,导致关联性的操作会非常麻烦。例如:登录=>添加购物车=>下单=>结算=>支付,如果是无状态的,服务器不知道其关联,则每次都要问一遍身份信息。
      解决方案:Cookie 技术:在请求和响应报文中写入 Cookie 信息来控制客户端的状态。

cookie

  • 明文传输:方便阅读、调试便利;信息裸奔,无隐私、不安全
  • 不安全:
    • 通信用明文,内容被窃听。比如,账号信息容易泄露。
    • 不验证通信方身份,遭遇伪装。比如,访问假的淘宝、拼多多
    • 无法证明报文的完整性,有可能被篡改。比如,网页上植入垃圾广告
      解决:用HTTPS的方式解决,也就是引入SSL/TLS层,使得在安全上达到了极致。
  • 性能:
    基于TCP/IP,使用了请求-应答的通信模式,性能关键在这两点。
    • 长连接
    • 管道网络传输:在同一个TCP连接里,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发送第二个请求,可以减少整体的响应时间。(服务器必须按照接受请求的顺序发送对这些管道化请求的响应,这导致了如果A请求比较耗时,后续的请求都会被阻塞住,这称为对头堵塞)
      注意:HTTP/1.1管道解决了请求的对头阻塞,没有解决响应的对头阻塞。并且该技术不是默认开启,后续讨论 HTTP/1.1 都是建立在没有使用管道化的前提。
    • 队头阻塞
      小结:HTTP/1.1 性能一般,后续的HTTP/2和HTTP/3都是在优化HTTP性能。

HTTP与HTTPS

  1. 区别:
  • HTTP 是超文本传输协议,信息是明文传输,存在安全风险。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
  • HTTP 在 TCP 三次握手后便可以进行 HTTP 报文传输;而 HTTPS 在 TCP 三次握手之后,还需要进行SSL/TLS 的握手,才可以进入加密报文传输。
  • HTTP 默认端口80,HTTPS 默认端口号443。
  • HTTPS 协议需要向CA(证书权威机构)申请数字证书,保证服务器的身份是可靠的。
  1. HTTPS 解决了 HTTP哪些问题
    HTTP 由于是明文传输,安全上存在三个风险:
  • 窃听风险
  • 篡改风险
  • 冒充风险

http与https

加入 SSL/TLS 协议,可以很好的解决上述风险:

  • 信息加密:交互信息无法被窃取,但你的账号会因为自身忘记而丢失。
  • 校验机制:无法篡改通信内容,篡改了就不能正常显示
  • 身份证书:保证淘宝是真的淘宝

HTTPS 是如何解决上面的三个风险的?

  • 混合加密实现机密性,解决了窃听的风险
  • 摘要算法保证完整性,解决了篡改风险
  • 将服务器公钥放入到数字证书中,解决了冒充的风险

混合加密:

混合加密

  • 在通信建立前采用非对称加密生成会话密钥
  • 在通信过程中使用会话密钥对明文进行对称加密

摘要算法+数字签名:

摘要算法

注意:哈希算法可以确保内容不会被篡改,但是并不能保证内容+哈希值不会被中间人替换,因为这里缺少对客户端收到的信息是否来源服务端的证明。

所以需要引入数字签名(私钥加密,公钥解密)来保证内容不被替换。
注意:这里加密的不是内容本身(非对称加密解密太耗时),而是对内容的哈希值加密。

数字签名

数字证书:
如果攻击者伪造私钥公钥,也能篡改内容,所以这里引入数字证书来对身份进行验证。

数字证书

将公钥+个人信息到第三方权威加密生成数字签名,并打包成数字证书,在发送内容时,不仅要用私钥对内容签名,还会发送数字证书。接收方收到后,先拿去数字证书到第三方权威机构去认证,如果是合法,才能证明源自真正的发送方。

  1. HTTPS是如何建立连接的?期间交互了什么?
    SSL/TLS 协议基本流程:
  • 客户端向服务器索要并验证服务器公钥
  • 双方协商生成会话密钥
  • 双方采用会话密钥进行加密通信
    TLS的握手阶段通过四次通信实现前两步,使用不同密钥交换算法,流程不一样,现在常用交换算法有:RSA 算法和ECDHE算法。
    基于RSA算法的TLS握手过程:

TSL握手过程

客户端校验数字证书的流程

屏幕截图 2025-07-15 010616

证书信任链
我们向CA申请的证书一般不是根证书签发的,而是由中间证书签发的,比如百度的证书,下图展示了三级证书:

三级证书

证书信任链验证流程:

证书信任链

为什么证书链这么麻烦,Root CA不直接颁发证书?
为了确保根证书的绝对安全,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题。

  1. HTTPS 的应用数据是如何保证完整性的?

TLS 在实现上分为握手协议和记录协议两层:

  • TLS握手协议(即TLS四次握手过程),负责协商加密算法和生成对称密钥,后续用此密钥来保护应用程序数据(HTTP数据)。
  • RLS记录协议负责保护应用程序数据并验证其完整性和来源,所以对HTTP数据加密是使用记录协议。
    TLS记录协议主要负责消息(HTTP数据)的压缩,加密以及数据的认证,过程如下图:

记录协议

记录协议完成后,最终的报文数据将传递到传输控制协议TCP层进行传输。

  1. HTTPS 一定安全可靠吗?
    背景:字节一面面试官提问:如果有假基站起了转发全部信息的作用,这样是不是假基站就获取到全部信息,从而造成信息泄露。
    场景分析:客户端通过浏览器向服务端发起HTTPS请求时,被假基站转发到了一个中间人服务器,于是客户端和中间人服务器完成了TLS握手,然后这个中间人服务器再与真正的服务端完成TLS握手。

HTTPS攻击

这种场景是有前提的,前提是用户点击接受了服务器的证书,就是图中红圈部分。

HTTPS攻击(2)

所以,HTTPS 协议本身到目前为止还是没有任何漏洞的,即使成功进行了中间人攻击,本质上是利用率客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书)

为什么抓包工具能截取HTTPS数据?
原理与中间人攻击一致。对于HTTPS连接来说,中间人攻击需要满足:

  • 中间人,作为客户端与真实服务器端建立连接,这一步不会有问题,因为服务端不会校验客户端的身份;
  • 中间人,作为服务端与真实客户端建立连接,这里就有客户端信任服务端的问题,也就是服务端必须有对应域名的私钥,而要拿到私钥只有:
    • 去网站服务端拿到私钥
    • 去CA处那域名签发私钥
    • 自己办法证书,且要被浏览器信任(起到CA的作用)

抓包工具只能采用第三种方法取得中间人的身份:在客户端安装 Fiddler 的根证书,客户端就会拿着中间人签发的证书去中间人自己的CA去认证。

如何避免被中间人抓取数据?
HTTPS 双向认证:

双向认证

HTTP/1.1、HTTP/2、HTTP/3 的演变

  1. HTTP/1.1 相比 HTTP/1.0 性能上的改进:
  • 使用长连接改善了 HTTP/1.0 短连接造成的性能开销
  • 支持管道 (pipeline) 网络传输,只要第一个请求发出去了,不必等其回来,就可以发送后面的请求,可以减少整体的响应时间

缺点:

  • 请求/相应头(Header)未经压缩就发送,首部信息越多延迟越大,只能压缩body部分
  • 发送冗长的首部,每次互相发送相同的头部造成浪费
  • 服务器按请求顺序响应,如果服务器响应慢,导致客户端一直请求不到数据,也就是队头阻塞
  • 没有请求优先级的控制
  • 请求只能从客户端开始,服务器只能被动响应
  1. HTTP/2 的优化
    HTTP/2协议是基于HTTPS的,安全性有保障。

http2

相比HTTP/1.1的改进:

  • 头部压缩:压缩头部,并且相同头部会去重(通过HPAC算法实现:客户端与服务器同时维护一张头信息表,所有字段存入该表,生成相应的索引号,通过发送索引号的方式替代相同字段,提高速度)。
  • 二进制格式:不再像 HTTP/1.1 中的纯文本形式的报文,全面采用二进制格式,头信息和数据体都是二进制,并且统称为帧:头信息帧 (Headers Frame) 和数据帧 (Data Frame)。计算机无需将明文的报文转成二进制,而是直接解析二进制报文,增加了数据传输效率。(这里面还有静态表,编码方式的学问)
  • 并发传输:HTTP/1.1中的管道只解决了请求队头阻塞,并没有解决相应队头阻塞,所以本质上没有解决问题;彻底解决问题的是HTTP/2基于帧 (frame) +流 (stream) 采用多路复用的解决了队头阻塞:一个TCP连接中多个请求可以并发发送、并发响应、无顺序限制。

多路复用

一个TCP包含多个stream,stream中可以包含一个或多个Message(即请求或响应)。针对不同的HTTP请求用独一无二的Stream ID来区分,接收端通过Stream ID有序组装为HTTP消息,不同的 stream 的帧是可以乱序发送的,因此可以并发不同 stream,也就是说HTTP/2可以并行交错地发送请求和响应。

  • 服务器主动推送资源:服务器也可以主动向客户端发送消息,客户端和服务器双方都可以建立stream,stream ID 通过奇偶来区分。

服务器推送

比如,客户端请求HTML文件后通常还需要CSS来渲染页面,HTTP/1.1中需要两次消息往返,而HTTP/2中,客户端在访问HTML时,服务器可以主动推送CSS文件,减少了消息的传递次数。

服务器推送2

HTTP/2的缺陷:
还是队头阻塞问题,只不过不是在HTTP层,而是在TCP层:
HTTP/2 是基于TCP协议传输数据,TCP是字节流协议,TCP层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给HTTP应用,所以分帧传输当前一个字节没有到达时,后面收到的字节数据只能存放在内核缓冲区中,只有所有字节数据到达后,http/2应用层才能从内核拿到数据。

http2缺陷

一旦发生了丢包,就会触发TCP重传机制,这样一个TCP连接中的所有HTTP请求都必须等待这个丢了的包被重传回来。而一个TCP连接中有很多流。
3. HTTP/3 的优化

HTTP/3把HTTP下层的TCP协议改成了UDP

http.3

基于UDP的QUIC协议可以实现类似TCP的可靠性传输,QUIC特点:

  • 无队头阻塞:当某个流丢包时,只会阻塞这个流,其他流不受影响。

quic

  • 更快建立连接:HTTP/1和HTTP/2协议的TLS与TCP分层,需要分批次来握手,先TCP握手,再TLS;HTTP/3在传输数据前只需要进行1RTT(往返时延)的QUIC协议握手,确认双方连接ID,便于实现连接迁移。HTTP/3内部包含了TLS(而不是与他分层),它会在自己的帧里携带TLS,加上QUIC使用的是TLS/1.3,因此只需要一个RTT就可以完成建立连接与密钥协商。

QUIC握手

甚至在第二次连接时,应用数据包可以和QUIC握手信息(连接信息+TLS信息)一起发送,达到0 RTT的效果。

QUIC连接

  • 连接迁移:TCP传输协议是通过四元组(源IP、源端口、目的IP、目的端口)确定一条TCP连接

tcp四元组

当移动设备网络从4G切换到WIFI时,意味着ip地址变换,必须断开连接,重新建立连接。而建立连接的过程包含TCP三次握手、TLS四次握手的时延,以及TCP慢启动的减速过程(拥塞控制:避免网络拥堵降低初始发送速率),给用户的感觉就是网络突然卡顿了,因此连接迁移成本高。
而QUIC通过连接ID来标记通信的两个端点,客户端和服务器端有各自的ID标记自己,即使移动设备网络变化导致IP地址变化,只要保存上下文信息(比如连接id,TLS密钥等),就可以无缝地复用原来的连接,实现连接迁移。
QUIC是一个在UDP之上的伪TCP+TLS+HTTP/2的多路复用的协议
注意:QUIC是新协议,对于很多网络设备,不知道QUIC,所以会把它当作UDP。而有的网络设备是会丢掉UDP包的,所以QUIC包就会被丢弃。

posted @ 2025-07-21 00:04  waterme  阅读(13)  评论(0)    收藏  举报