HSTS 严格传输安全

HSTS 通过响应头告诉浏览器以后只能用 HTTPS 访问这个站点,防止协议降级攻击。

#type / concept #status / evergreen #tech / security #resource / http #platform / browser

[!info] related notes

HSTS 严格传输安全

一句话定义

Strict-Transport-Security(HSTS)告诉浏览器:以后只能通过 HTTPS 访问这个站点,并把后续 HTTP 访问自动改为 HTTPS。

它要解决什么问题

即使网站启用了 HTTPS,用户第一次访问时可能通过 HTTP:

用户输入 http://example.com

中间人拦截 HTTP 请求(还没到 HTTPS 重定向)

中间人返回伪造响应

用户被骗

HSTS 的思路是:浏览器记住”这个站点只能用 HTTPS”,下次直接用 HTTPS,跳过 HTTP 阶段。

核心机制

服务器返回:

Strict-Transport-Security: max-age=31536000; includeSubDomains

浏览器收到后,在 max-age 时间内:

  • 自动把 http:// 改成 https://
  • 拒绝加载这个站点的 HTTP 资源
  • 忽略用户点击的”继续访问”确认

重要前提

浏览器只在以下条件下接受 HSTS 头:

  • 响应是通过 HTTPS 返回的
  • 证书没有错误
  • 不是自签名证书(首次访问时)

如果通过 HTTP 返回 HSTS 头,浏览器会忽略它。

指令详解

max-age

Strict-Transport-Security: max-age=31536000

浏览器记住 HSTS 策略的秒数。31536000 = 1 年。

includeSubDomains

Strict-Transport-Security: max-age=31536000; includeSubDomains

HSTS 策略也适用于所有子域名。比如 example.com 设了 includeSubDomains,api.example.comwww.example.com 也必须支持 HTTPS。

风险:如果某个子域不支持 HTTPS,设了 includeSubDomains 后该子域会不可访问。

preload

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

申请加入浏览器内置的 HSTS preload list。新用户第一次访问就能享受 HSTS 保护,不需要先收到一次 HSTS 响应。

申请条件(以 Chrome 为例):

  • max-age 至少 31536000 秒(1 年)
  • 必须有 includeSubDomains
  • 必须有 preload
  • 所有子域都必须支持 HTTPS
  • 必须在根域返回 HSTS 头

回滚成本很高:一旦加入 preload list,从列表中移除需要很长时间。不要在不了解所有子域情况时随意加 preload。

推荐配置

保守(推荐起步)

Strict-Transport-Security: max-age=31536000; includeSubDomains

激进(确认所有子域支持 HTTPS 后)

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

边界与易混淆点

  • HSTS 不等于”全站 HTTPS”:HSTS 是告诉浏览器用 HTTPS,但服务器本身仍然需要配置 HTTPS 证书和重定向。
  • 首次访问仍然不安全:用户第一次访问时浏览器还没有 HSTS 记录,仍然可能通过 HTTP。preload 可以解决这个问题。
  • max-age=0 用于取消 HSTS:如果误配了 HSTS,可以用 max-age=0 让浏览器清除记录,但只对已经访问过的用户有效。
  • HSTS 只影响浏览器:API 调用方(如 curl、后端服务)不受 HSTS 影响。
创建于 2026/5/24 更新于 2026/5/27