先说结论:浏览器什么时候开始"记住"HSTS?
很多教程只告诉你"配置HSTS",但没说清楚浏览器到底什么时候开始强制执行HTTPS。这里直接给结论:
- 浏览器在第一次收到Strict-Transport-Security响应头之后,就会立即将域名加入HSTS列表,不需要等待max-age秒。
- max-age的含义是:记住这个策略的有效期有多长,而不是"多少秒之后才开始生效"。
举个例子:你配置max-age=31536000(一年),用户第一次访问你的HTTPS网站,响应头里带了Strict-Transport-Security: max-age=31536000,浏览器当场就把你的域名加入HSTS列表。从这一刻起,未来一年之内,这个浏览器访问你的域名时,会自动把http://替换成https://,即使用户手动输入http://也不会生效。
max-age的时间是怎么计算的?
max-age的单位是秒,计时起点是浏览器收到响应头的那一刻,不是服务器配置的时间,也不是域名注册的时间。
每次浏览器收到Strict-Transport-Security响应头,都会刷新过期时间。刷新规则很简单:新的过期时间 = 当前时间 + max-age秒。
这意味着:只要用户还在持续访问你的网站,HSTS策略就会一直续期,永远不会过期。只有用户超过max-age秒没有访问你的网站,浏览器才会把你的域名从HSTS列表中移除。
这也是为什么推荐设置max-age=31536000(一年)—— 普通用户很难一年都不访问一个网站,所以实际上HSTS策略几乎是永久生效的。
首次访问 vs 后续访问:攻击窗口在哪里?
HSTS有一个本质缺陷:首次访问是走的HTTP还是HTTPS?
答案是:首次访问如果用户输的是http://,浏览器还没有你的HSTS记录,所以这次请求是不加密的。这就是所谓的"首次访问攻击窗口"(TOFU,Trust On First Use)。
攻击者可以在用户第一次访问时实施中间人攻击,因为此时HSTS还没有生效。解决这个问题的方案是HSTS Preload—— 把域名提前写进浏览器的内置列表,连首次访问都会被强制跳转HTTPS。
后续访问(第二次及以后)就安全了:浏览器本地已经有HSTS记录,会在发起请求之前就把http://替换成https://,中间人根本没有机会攻击。
浏览器重启、清除缓存后,HSTS记录还在吗?
这是很多人困惑的地方,分情况说清楚:
- 普通重启浏览器:HSTS记录还在。HSTS列表是持久化存储的,存在浏览器的本地数据库中,不是会话级的cookie。
- 清除浏览历史记录:Chrome/Edge中,清除"浏览历史记录"不会删除HSTS记录;需要到
chrome://net-internals/#hsts里手动删除。 - 无痕模式:Chrome的无痕模式不继承普通模式的HSTS记录,关闭无痕窗口后HSTS记录也不会保留。
- Firefox:HSTS记录存在
SiteSecurityServiceState.txt文件中,清除"离线网站数据"会删除它。
所以,max-age过期之前,只要用户没有手动清除HSTS记录,浏览器重启后依然会强制执行HTTPS。
如何验证浏览器是否已经"记住"了你的域名?
最可靠的方法是用浏览器自带的工具查看:
Chrome / Edge(Chromium内核)
访问 chrome://net-internals/#hsts,在"Query HSTS/PKP domain"输入框里输入你的域名,点击Query。
如果返回了static_sts_domain:或dynamic_sts_domain: true,说明浏览器已经记住了你的HSTS策略。dynamic_sts_domain表示是通过响应头动态添加的,static_sts_domain表示是通过Preload列表内置的。
Firefox
地址栏输入about:support,找到"配置文件文件夹",打开里面的SiteSecurityServiceState.txt,搜索你的域名。
命令行验证
用curl发送HTTPS请求,查看响应头是否包含Strict-Transport-Security:
curl -I https://www.youres.cn 2>/dev/null | grep -i strict
max-age设置为0会怎样?
max-age=0是一个特殊的"退出机制"。当浏览器收到max-age=0的Strict-Transport-Security响应头时,会立即将你的域名从HSTS列表中移除。
这个机制主要用于:
- 你想要关闭HSTS,但有些用户浏览器里已经有记录了
- 你先配置了一个较短的max-age做测试,现在想让它过期
注意:max-age=0不会立即清除已经通过Preload列表内置的HSTS记录。要移除Preload记录,需要到
HSTS Preload:让"记住"时间提前到首次访问之前
前面说了,普通HSTS的缺陷是首次访问有攻击窗口。HSTS Preload解决了这个问题。
Preload的原理:域名被写进浏览器的内置HSTS列表(硬编码在Chromium、Firefox的源代码中),浏览器在第一次访问之前就已经"记住"了你的域名,连首次HTTP请求都不会发出。
Preload的要求:
- max-age必须至少31536000(一年)
- 必须包含includeSubDomains指令
- 必须包含preload指令
- 必须通过
的审核
一旦进入Preload列表,撤销非常困难——需要等待用户更新浏览器版本,或者到
实战建议:max-age该设置多久?
综合各方最佳实践,推荐的分阶段策略:
- 测试阶段:max-age=86400(一天)。如果配置出错,最坏情况下用户一天后就能恢复正常访问。
- 确认稳定后:max-age=31536000(一年)。这是生产环境的推荐值。
- 准备提交Preload时:max-age=63072000(两年),同时加上includeSubDomains和preload指令。
不要设置太短的max-age(比如300秒),这样用户关闭浏览器再打开,HSTS策略就失效了,等于白配置。
常见问题答疑
Q:我用HTTP访问,浏览器会记住HSTS吗?
A:不会。HSTS响应头只有走HTTPS时才会被浏览器处理。如果你只能通过HTTP访问,说明证书有问题,浏览器也不会记住HSTS。
Q:max-age设置后多久能在浏览器里看到效果?
A:立即生效。用户第一次访问HTTPS页面后,第二次访问时HSTS就已经生效了。
Q:子域名会自动被记住吗?
A:只有配置了includeSubDomains指令才会。否则父域名的HSTS策略不会影响子域名。
Q:浏览器记住HSTS后,证书错误还能"继续访问"吗?
A:不能。HSTS生效后,证书错误会导致浏览器直接拒绝访问,没有"继续访问"的选项。这也是为什么测试阶段要用短的max-age。
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论