Web 安全

HSTS (HTTP 严格传输安全)

约 4 分钟阅读

什么是 HSTS

HSTS (HTTP Strict Transport Security) 是一种安全机制,Web 服务器通过它指示浏览器「今后访问此域名必须使用 HTTPS」。通过在 HTTP 响应头中添加 Strict-Transport-Security 来启用,其规范由 RFC 6797 (2012 年 11 月) 标准化。

未设置 HSTS 时,用户访问 http://example.com 时,在服务器重定向到 HTTPS 之前的短暂瞬间,通信以明文进行。这一瞬间可能遭受中间人攻击 (SSL 剥离)。接收到 HSTS 策略的浏览器,之后在发送该 URL 前就会将其改写为 HTTPS,因此这次明文往返本身不再发生。

另一个支柱是对证书错误的处理。在 HSTS 生效的域名上,如果证书验证失败,浏览器必须中断连接,用户无法像普通警告页面那样「知晓风险后继续访问」。即使攻击者准备了伪造的证书,用户也无法通过操作强行通过,这正是它与普通 HTTPS 的区别。

另一方面,浏览器只有在接收到响应头之后才知道这项指示。首次访问该域名时 HSTS 不起作用,RFC 自身也将此列为弱点。后文介绍的 Preload 列表正是为填补这一缺口而设计的机制。

HSTS 的配置与指令

HSTS 通过以下响应头配置。

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

  • max-age:浏览器记住 HSTS 策略的秒数。31536000 (1 年) 也是 Preload 列表注册要求作为下限的值,因此被广泛使用。初次部署时从 300 (5 分钟) 或 86400 (1 天) 开始,确认无问题后逐步延长。
  • includeSubDomains:将 HSTS 也应用于子域名。启用前需确认 api.example.comcdn.example.com 等所有子域名都支持 HTTPS。仅使用 HTTP 的子域名将无法访问。
  • preload:表示有意注册到 HSTS Preload 列表的标志。RFC 6797 定义的指令只有 max-age 和 includeSubDomains 两个,preload 是为浏览器端的列表后来追加的、规范之外的标志。由于规范规定应忽略未知的指令,仅添加该标志不会产生任何效果,注册需要另行申请。

安全头中,HSTS 的配置项较少,能可靠地强制通过 TLS/SSL 进行加密通信。但需注意,一旦被浏览器记住,在 max-age 到期之前无法将该域名恢复为 HTTP。请先确认 HTTPS 的支持范围,并采用从较小的 max-age 开始逐步延长的步骤。

HSTS Preload 列表的工作原理

普通 HSTS 存在「首次访问问题」。由于浏览器在首次 HTTPS 访问时才接收 HSTS 头,用户首次访问该域名时 HSTS 不起作用。

应对这个问题的是 HSTS Preload 列表。它是内置于浏览器中的 HSTS 支持域名清单,以 Chrome 源代码中包含的列表为基础,Firefox、Safari、Edge 也各自维护基于它的列表。注册申请通过 hstspreload.org 提交,注册后,即使用户从未访问过该域名,也会从第一次访问起强制使用 HTTPS。

Preload 列表注册要求:

  • 使用有效的数字证书
  • 如果在 80 端口上提供服务,需在同一主机名上从 HTTP 重定向到 HTTPS
  • 所有子域名都通过 HTTPS 提供服务 (若存在 www 的 DNS 记录,www 也属于对象范围,包括未对外公开的内部子域名)
  • max-age 为 31536000 (1 年) 以上
  • 包含 includeSubDomainspreload 指令

需要注意的是难以撤回。即使申请移除,该变更通过浏览器更新送达用户也需要数月时间,并且官方明确说明不保证在 Chrome 以外的浏览器上生效。新注册同样需要数月才能进入稳定版。注册前请仔细确认所有子域名都支持 HTTPS。

另外,截至 2026 年 8 月,hstspreload.org 表明的立场是,推荐使用 HSTS 本身,但不推荐注册到 Preload 列表。原因是 Chrome 和 Safari 已经开始不论是否存在 HSTS 策略,都将 HTTP 的页面跳转升级为 HTTPS,Preload 起作用的场景仅限于该升级被攻击者阻断的情况。请将部署 HSTS 与注册 Preload 列表作为两个独立的判断来对待。

HSTS 部署注意事项与渐进式方法

HSTS 虽然强大,但配置错误可能导致站点无法访问。推荐以下渐进式方法。

  1. 步骤 1:设置 max-age=300 (5 分钟),确认整个站点在 HTTPS 下正常运行
  2. 步骤 2:延长到 max-age=86400 (1 天),运行约一周确认无问题
  3. 步骤 3:扩展到 max-age=31536000; includeSubDomains
  4. 步骤 4:仅在选择注册 Preload 列表时,确认上一节的注意事项后再添加 preload 并提交申请

特别需要注意的是以 HTTP 引用自有域名或其子域名的地方。启用 includeSubDomains 后,浏览器会将这些引用改写为 HTTPS,若存在不支持 HTTPS 的子域名,加载本身就会失败。启用前请确认包括测试环境和内部用途在内的所有子域名都能通过 HTTPS 响应。此外,其他公司域名的 CDN 通过 HTTP 分发的资源不在 HSTS 的适用范围内,无论是否设置 HSTS,浏览器都会将其作为混合内容 (Mixed Content) 拦截。

CSPupgrade-insecure-requests 指令配合使用,可以自动将页面内的 HTTP 资源引用改写为 HTTPS,缓解过渡期间的混合内容问题。

常见误解

已经重定向到 HTTPS 就不需要 HSTS
HTTP 到 HTTPS 重定向期间,初始请求以明文发送。这一瞬间可能遭受中间人攻击 (SSL 剥离)。HSTS 在浏览器端将 HTTP 请求改写为 HTTPS,防御了重定向无法防止的攻击。
设置 HSTS 后立即对所有用户生效
普通 HSTS 在浏览器接收到头后才生效,因此首次访问时不受保护。从首次访问起强制的手段是 HSTS Preload 列表,但注册后需要数月才能恢复原状,因此请在确认目标域名及其所有子域名能够长期维持 HTTPS 之后再作判断。
分享

相关术语

相关文章