- Published on
HSTS (HTTP 严格传输安全)
在现代 Web 中,全站 HTTPS 已是安全标配。然而,即使用户的最终访问是 HTTPS,其第一次尝试访问网站时,仍可能输入 http://
地址。服务器通过 301/302 重定向将其引导至 HTTPS,但这个初始的 HTTP 请求过程,仍然暴露在网络中,容易受到如 SSL 剥离 (SSL Stripping) 等中间人攻击。HSTS (HTTP Strict Transport Security) 是一种由服务器声明、由浏览器强制执行的安全策略,其核心目的就是从根本上消除这个不安全的首次连接,强制客户端只能通过 HTTPS 进行通信。
HSTS 的工作流程:两阶段的“升级”
HSTS 的工作机制是一个“首次信任 (Trust on First Use)”并随后强制执行的过程,我们可以将其分为首次访问和后续访问两个阶段。
阶段一:首次访问 - 学习并记忆策略
当用户首次访问网站时(或在 HSTS 策略过期后),标准的重定向流程依然存在。
- 用户请求 HTTP: 用户在浏览器输入
http://example.com
。 - 服务器 301 重定向: 服务器接收到 HTTP 请求后,返回一个状态码为
301 Moved Permanently
(或302 Found
) 的响应,其Location
头指向https://example.com
。 - 浏览器跳转至 HTTPS: 浏览器遵循重定向,向
https://example.com
发起新的请求。 - 服务器下发 HSTS 策略: 在对 HTTPS 请求的响应中,服务器加入一个关键的 HTTP 头:
Strict-Transport-Security
。
Strict-Transport-Security: max-age=31536000; includeSubDomains
- 浏览器记录策略: 浏览器收到这个响应头后,会立即在内部的一个 HSTS 列表(“记忆”)中记录下:在接下来的
max-age
秒内,访问example.com
及其所有子域名,都必须强制使用 HTTPS。max-age
: 策略的有效时长(以秒为单位)。每次浏览器收到这个头,都会刷新这个过期时间。includeSubDomains
: 一个可选指令,意味着此策略同样适用于该域名的所有子域名。
阶段二:后续访问 - 浏览器的内部强制跳转
一旦浏览器“记住”了某网站的 HSTS 策略,后续的访问行为将发生根本性改变。
307 Internal Redirect
当用户再次尝试用 http://
访问时,浏览器不会发出任何网络请求。它会直接在内部将 URL 从 http
修改为 https
,然后才发起网络连接。在开发者工具的网络面板中,可以看到一个状态码为 307 Internal Redirect
的“伪请求”,它代表的就是这次由浏览器自身完成的、内存中的强制跳转。
HSTS 预加载列表 (Preload List) - 弥补首次访问的漏洞
HSTS 的“首次信任”模型依然存在一个理论上的漏洞:第一次访问时的那个 301
重定向仍然可能被中间人攻击。为了解决这个问题,主流浏览器维护了一个HSTS 预加载列表。
这是一个硬编码在浏览器内部的域名列表。如果你的域名被加入了这个列表,那么即使用户是有史以来第一次访问你的网站,浏览器也会直接执行 307 内部重定向
,从根本上消除了所有不安全的 HTTP 请求。
- 在 HSTS 头中加入
preload
指令:Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
- 通过 hstspreload.org 提交域名,等待被各大浏览器厂商收录。这是一个不可逆的操作,需要审慎进行。