HTTP 关于 HTTPS SSL/TLS 、 HTTP/2 特性

HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 的安全版本,通过在 HTTP 下方加入 SSL/TLS 加密层 ,实现对传输数据的加密、服务器身份认证和数据完整性保护。它默认使用端口 443(HTTP 使用 80)。

HTTP/1.1 、HTTPS 、 HTTP/2 、 HTTP/3 协议结构

SSL/TLS

SSL/TLS 协议并不属于传统的 OSI 或 TCP/IP 模型中的单一层次,而是在传输层(TCP)之上、应用层(HTTP)之下 ,作为一个安全套接层 为上层应用提供加密、认证和完整性保护。其内部又分为两层:记录协议(TLS Record Protocol)握手协议(TLS Handshake Protocol)

TLS 握手是客户端与服务器之间建立安全通信的核心步骤,目的是协商加密算法、交换密钥、验证身份,并生成用于后续加密的会话密钥

TLS 1.2 握手过程(HTTP/2)

TLS 1.3 握手过程 (HTTP/3)

TLS 1.3 相比 TLS 1.2 大幅简化了握手流程,减少了往返次数(RTT),并移除了不安全的加密套件。

第一次握手:客户端 → 服务器(Client Hello)

  • 作用:客户端发起连接,发送 Client Hello 消息。
  • 内容 :支持的 TLS 1.3 版本、加密套件(AEAD 类)、随机数、密钥共享参数(key_share) ,以及 SNI 扩展(服务器名称指示),指明要访问 api.juejin.cn

第二次握手:服务器 → 客户端(Server Hello + 加密握手消息)

  • Server Hello(明文):服务器选择 TLS 1.3 版本、加密套件,返回自己的 key_share,生成服务器随机数。此时双方已计算出 Pre‑Master Secret 并派生出握手密钥。
  • Change Cipher Spec :这是 兼容性消息 (固定值 0x01),在 TLS 1.3 中不是必须的,但某些实现会发送以帮助中间件识别协议切换。
  • 第一个 Application Data :实际是加密的 EncryptedExtensions + Certificate + CertificateVerify 消息(因为 TLS 1.3 中除 ClientHello/ServerHello 外所有握手消息都加密)。
  • 第二个 Application Data :加密的 Finished 消息(服务器端)。

服务器在这一轮完成了握手消息的发送,并已经可以发送应用数据。

第三次握手:客户端 → 服务器(Client Finished)

  • Change Cipher Spec:同样是兼容性消息(可选)。
  • Application Data :加密的 Finished 消息(客户端),用于验证握手完整性。

至此,双向握手完成,连接进入 ESTABLISHED 状态,双方可使用 1‑RTT 密钥保护应用数据。

SSL

SSL (Secure Sockets Layer,安全套接层) 是一项历史悠久的网络安全协议。在浏览器地址栏看到的 🔒(安全锁)图标,以及网址开头的 https://,都意味着当前网站正在使用 SSL 技术,确保你的数据在网络上被安全地加密传输。

SSL协议经历了多个版本更新,主要有SSL 1.0、SSL 2.0和SSL 3.0。其中,SSL 2.0版本存在众多安全漏洞,因此逐渐被淘汰。SSL 3.0虽然改善了很多安全问题,但也不再被推荐使用。

TLS 是 SSL 的继任者 ,TLS 1.2 和 TLS 1.3 是目前广泛使用的主流安全协议

HTTPS 项目 生成证书

openssl 命令快速生成一个自签名的证书

bash 复制代码
openssl genrsa -out private-key.pem 2048
openssl req -new -key private-key.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey private-key.pem -out certificate.pem

HTTP/2 核心特性

HTTP/2(超文本传输协议第二版)是 HTTP 协议的第二个主要版本,基于 Google 的 SPDY 协议开发,于 2015 年正式标准化(RFC 7540)。

RFC 9113: HTTP/2 , 废除了RFC 7540 和 8740。

多路复用

在单一的 TCP 连接上,可以并行、交错地发送多个请求和响应,而无需等待。这显著提升了页面加载速度,可比 HTTP/1.1 快 15%-50% ,并降低了延迟。

为什么 HTTP/1.1 很慢?

HTTP/1.1 在传输数据时存在一个先天的性能瓶颈:队头阻塞

  • 串行处理 :在一个 TCP 连接上,请求必须严格按照"请求1 -> 响应1 -> 请求2 -> 响应2"的顺序进行,前一个请求未完成,后面的所有请求都会被阻塞排队。
  • 并发补偿 :为了缓解这个问题,浏览器会 为每个域名开启多个(通常是6-8个)TCP 连接并行加载资源。但这种方式会消耗更多服务器资源,增加连接管理的开销,在高延迟网络下效果依然有限。

如何实现多路复用?

HTTP/2 的解决方案是在 HTTP 层和 TCP 层之间,增加了一个全新的 二进制分帧层,将通信单位细化到无法再分的小"帧"。

多路复用是 HTTP/2 协议 的特性,它在 应用层 实现,具体由浏览器(客户端)和 Web 服务器完成。

浏览器端(发送与接收)

  • 发送时 :浏览器将多个请求拆分成带 Stream ID 的二进制 ,交错发送到同一个 TCP 连接上。
  • 接收时 :浏览器根据帧头的 Stream ID 将收到的帧重组回原始的请求/响应数据。

这些操作完全在浏览器的 HTTP/2 协议栈 中完成,不依赖底层网络。

二进制分帧

HTTP/2 不再使用 HTTP/1.1 的纯文本格式,而是将所有消息分割为更小的二进制"帧"进行传输和解析,效率更高。

帧格式

http 复制代码
HTTP Frame {
  Length (24),
  Type (8),

  Flags (8),

  Reserved (1),
  Stream Identifier (31),

  Frame Payload (..),
}
  • 长度 (24 bits):帧负载的长度(不包括头部),最大 16,384 字节 (2^14)。
  • 类型 (8 bits):帧的类型,决定负载的格式和语义。
  • 标志 (8 bits):特定于帧类型的布尔标志。
  • 流标识符 (31 bits):唯一标识一个流,用于将帧归属到特定的请求/响应。最高位保留。
  • 帧负载:可变长度,依据帧类型不同而不同。

头部压缩

HTTP/2 引入了 HPACK 压缩机制,专门用于压缩 HTTP 请求和响应的头部字段,以解决 HTTP/1.1 中头部重复、冗余导致的大开销问题。

为什么需要头部压缩?

  • HTTP/1.1 头部是纯文本,每个请求都携带大量重复字段(如 CookieUser-AgentAccept 等)。
  • 头部大小可达数百字节甚至上千字节,频繁传输会消耗带宽、增加延迟。
  • 尤其对于小资源(如 API 响应),头部可能比 body 还大。

HPACK 的核心原理?

1、静态字典(Static Table)

  • 预定义了一个包含 61 个常见头部字段的静态表(如 :method: GET:status: 200content-type 等)。
  • 每个条目都有一个索引号。发送时可以用索引代替完整字符串,例如用 2 表示 :method: GET

2、动态字典(Dynamic Table)

  • 在连接过程中动态构建,用于存储之前出现过的自定义头部(如 X-Custom-Header)。
  • 双方共同维护,并可通过 SETTINGS 帧调整大小。
  • 后续请求中,相同头部可以用索引引用,无需重复发送。

3、哈夫曼编码(Huffman Coding)

对头部值(如 text/html,application/json)进行哈夫曼编码,进一步减少字节数。

压缩过程?

发送端:

  1. 将头部字段拆分为键和值。
  2. 先在静态字典中查找索引;找不到则在动态字典中查找。
  3. 如果找到,发送索引。
  4. 如果未找到,使用字面量形式(键和值),并可选地将该条目加入动态字典。
  5. 对字符串值进行哈夫曼编码(可选)。

接收端:

  • 解码时还原为原始头部字段,并更新动态字典。

服务器推送 (Server Push)

允许服务器在客户端明确请求前,主动推送其可能需要的资源(如 CSS、JS),减少请求次数

问题:推送未请求的资源浪费带宽,缓存命中率难控制,现在更推荐使用 103 Early Hintspreload

HTTP/2 推送的替代方案:103 Early Hintspreload

103 Early Hints

HTTP/1.1 和 HTTP/2 中引入的信息性状态码(由 RFC 8297 定义)。

HTTP 103 Early Hints 是一个信息型 HTTP 状态码,允许服务器在最终响应前,先发送一个包含"提示"的中间响应,让浏览器能提前进行资源加载或连接准备,从而利用服务器的"思考时间"优化性能

在 Chrome 开发者工具的 Network 面板中,103 状态码本身通常不会单独显示为一行 ,而是将 103 中包含的 Link 头部归类到"Early hints headers"这个折叠区域。

"Early hints headers" 下出现了 Link: </style.css>; rel=preload; as=style,这表示浏览器已经收到了 103 响应,并从中提取出了预加载提示。

HTTP 响应头中的 Link 字段用于表达当前资源与其他资源之间的关联关系 ,类似于 HTML <link> 标签的功能,但位于 HTTP 协议层面。它允许服务器在响应中携带链接信息,让客户端(如浏览器)在不解析 HTML 的情况下提前获知并采取相应动作,从而优化性能。

  • 资源预加载 (preload)Link: </css/main.css>; rel=preload; as=style。告知浏览器提前加载后续需要的资源(如样式表、脚本、字体等),减少页面渲染等待时间。

  • 预连接 (preconnect)Link: <https://example.com>; rel=preconnect, 提前与第三方源建立连接(DNS、TCP、TLS),加速后续请求。

  • 预取 (prefetch)Link: </next-page.html>; rel=prefetch, 在空闲时预取下次导航可能用到的资源。

  • DNS 预解析 (dns-prefetch)Link: <https://example.com>; rel=dns-prefetch , 提前解析域名。

项目地址 https://localhost:5177/react19-vite-app/bug-view

发起请求 https://localhost:8843/api/html

响应头有返回 link </style.css>; rel=preload; as=style

针对 link ,会根据 link 信息发起请求

node 相关接口代码

为什么 HTTP/2 的服务器推送(Server Push)逐渐被 103 + preload 取代?

HTTP/2 Server Push 的问题:

  • 推送的资源可能已被浏览器缓存(浪费带宽)。
  • 优先级难以控制,可能导致关键资源被非关键资源抢占。
  • 连接复用容易出错(例如推送了但不使用的资源)。
  • Chrome 等浏览器已弃用并移除对 HTTP/2 Server Push 的支持(2022 年起)。

流优先级

HTTP/2 允许客户端为每个流(即每个请求/响应)指定 优先级,以告诉服务器哪些资源更重要、应该更早或分配更多带宽。这有助于优化页面加载性能,尤其是首屏关键资源。

HTTP/2 使用 依赖树(Dependency Tree)权重(Weight) 来表达优先级。

流依赖(Stream Dependency)

  • 一个流可以依赖于另一个流,表示它应该在依赖的流之后处理(更次要)。
  • 例如:script.js 依赖于 style.css,则表示服务器应优先发送 style.css
  • 所有流最终都隐式依赖于 根流(ID 为 0x0)。

权重(Weight)

  • 每个流可以分配一个 1~256 的整数权重,默认 16。
  • 同级的流按权重比例分配带宽(资源)。
  • 例如:同级两个流,权重 200 和 100,则分别获得约 2/3 和 1/3 的带宽。

排他性标志(Exclusive Flag)

  • 将一个流设置为排他依赖时,该流的父流原有的所有子流会变为当前流的子流。
  • 简化表达:Stream A 排他依赖 Stream PP 的其他旧子流成为 A 的子流。

优先级信息的传递

  • 优先级信息通过 HEADERS 帧PRIORITY 帧 发送。
  • HEADERS 帧(创建流时)可以携带优先级字段(依赖流 ID + 权重 + 排他标志)。
  • PRIORITY 帧(独立发送)可用于随时调整已存在流的优先级。

HTTP/2 请求头

HTTP/1.1 的 请求行GET /index.html HTTP/1.1)在 HTTP/2 中被拆分为多个以 : 开头的伪头字段。

HTTP/2 伪头字段必须在普通头字段之前发送,且不能重名。

HTTP/2 单个HEADERS 帧载荷默认最大 16KB ,但可以通过 SETTINGS_MAX_FRAME_SIZE 调整到 16MB。如果头部超过单帧大小,可以连续发送多个 CONTINUATION进行拼接(但性能可能受影响)。

HTTP/2 协议协商机制:ALPN 与 Upgrade 头

HTTP/2 的协商方式取决于连接是否使用 TLS(即 HTTPS 或 HTTP)。主流方式是 ALPN (Application-Layer Protocol Negotiation),主要用于加密连接;而明文的 HTTP/2(h2c)则需要使用 Upgrade 头

ALPN 是 TLS 扩展,允许客户端和服务器在 TLS 握手期间协商出应用层协议(如 h2http/1.1)。

ALPN如何工作?

ALPN的协商过程非常高效,它巧妙地融合在了TLS握手这个必经之路上,没有额外的网络开销。

  1. 客户端(如Chrome)发送 ClientHello :在TLS握手的第一步中,客户端就通过一个扩展,主动列出自己支持的应用层协议列表,并按优先级排序(例如,首选h2,其次为http/1.1)。
  2. 服务器(如Nginx)回复 ServerHello :服务器收到列表后,会从其中选择一个自己同样支持的协议。这个选择结果会通过ServerHello消息,以明文形式清晰地告知客户端。
  3. 达成一致:至此,通信双方就明确了后续将使用何种协议(如HTTP/2),整个过程在TLS的第一次往返(1-RTT)中就完成了。

浏览器如何自动设置优先级(Chrome 的资源优先级)

Chrome 浏览器有一套自动、复杂的优先级调度机制。它的核心逻辑是:让最关键的资源插队,让次要资源待命,从而优先保障用户的第一印象。

不过,还可以手动控制:

  1. fetch 请求,options 配置 priority 属性
  2. 调整元素属性 : 对于图片(<img>)、脚本(<script>)等元素,直接添加 fetchpriority 属性
  3. 使用资源提示 (<link>) : 通过 <link> 标签发出资源提示,可以对优先级进行间接控制。
    • rel="preload" :用于提高 当前页面关键资源 的优先级,指示浏览器尽早加载,通常在 <head> 标签内声明。
    • rel="prefetch" :用于降低 当前页面次要资源的优先级,指示浏览器在空闲时预取。
    • rel="preconnect" :不与具体资源挂钩,而是提醒浏览器尽早建立连接

最后

  1. RFC 9113: HTTP/2
  2. rfc7541
相关推荐
KaMeidebaby1 小时前
卡梅德生物技术快报|细胞周期检测抗原流式分析:参数调试、软件拟合与问题排查
网络·人工智能·python·网络协议·tcp/ip·算法·机器学习
Irissgwe1 小时前
7、传输层协议 TCP
网络·网络协议·tcp/ip·tcp·三次握手·四次挥手
j7~1 小时前
【Linux】网络基础(1)--之局域网、广域网、OSI,网络协议、TCP/IP结构模型、网络传输等知识详解
网络·网络协议·tcp/ip·协议·osi·mac地址·报头
xxlyss&w1 小时前
Tenda AC9 V15.03.05.19(6318)_CN FUN_000384c8 — HTTP CGI 命令注入
网络·网络协议·http
酉鬼女又兒2 小时前
零基础入门计算机网络:MAC地址、IP地址与ARP协议全面解析(含考研真题详解)
网络·网络协议·tcp/ip·计算机网络·考研·macos·职场和发展
8125035332 小时前
第 6 篇:ARP 协议——IP 管远方,MAC 管眼前,它来搭桥
网络·网络协议·tcp/ip
xxlyss&w2 小时前
Tenda AC9 V15.03.05.19(6318)_CN FUN_000384c8 — HTTP CGI 命令注入漏洞分析
网络·网络协议·http
xlq223223 小时前
65.tcp—done
服务器·网络协议·tcp/ip
汤愈韬13 小时前
IPSec-NAT穿越原理和配置
网络·网络协议·安全·网络安全·security