HSTS max-age 到底是什么
HSTS(HTTP Strict Transport Security)是网站安全的重要一环,而 max-age 参数则是整个策略的核心——设错了,要么浏览器根本不记,要么记了没法改。本文整理了6个 Nginx HSTS max-age 设置时最常见的错误,逐一给出排查方法和正确配置。
max-age 告诉浏览器:在多少秒内,访问这个域名时必须使用 HTTPS。比如 max-age=31536000 就是一年。这个参数有几个关键点:
- 单位是秒,不是天
- 设为 0 会立即让浏览器忘记 HSTS(用于紧急回退)
- preload 要求 max-age 至少两年(63072000 秒)
错误一:max-age 单位搞错,写成天数
这是最常见的低级错误。Nginx 配置里直接写了天数:
# 错误写法
add_header Strict-Transport-Security "max-age=365; includeSubDomains" always;
# 正确写法
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
365 秒只有6分钟,浏览器几乎不会生效。一年是 31536000 秒,两年是 63072000 秒。
错误二:忘记加 always 参数,404页面安全头丢失
Nginx 的 add_header 有个坑:如果在子层级(比如 location 块)写了 add_header,父层级的 add_header 会被覆盖,导致 404 等错误页面没有 HSTS 头。
解决方法有两个:
- 在每条
add_header后面加always参数 - 把 HSTS 配置放在
server块,而不是location块
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
相关阅读:Nginx add_header always参数用法详解:为什么安全头在错误页面消失了
错误三:max-age 先用小值测试,但忘记改大
很多教程建议先用 max-age=60(60秒)测试,确认没问题再改大。但问题是:测试通过后,很多人忘了改回来。
正确做法是用分阶段方案:
- 第一阶段:
max-age=60,测试 1-2 天 - 第二阶段:
max-age=86400(1天),观察 1 周 - 第三阶段:
max-age=31536000(1年),稳定运行 - preload 前:
max-age=63072000(2年)+preload指令
相关阅读:Nginx HSTS max-age设置建议:分阶段配置方案与最佳实践
错误四:includeSubDomains 和 max-age 同时配置但逻辑矛盾
有些配置里 max-age 设得很短,但却加了 includeSubDomains; preload,这是矛盾的——preload 要求 max-age 至少两年,短了提交 hstspreload.org 会被拒。
提交 preload 前,响应头必须同时满足:
max-age=63072000(至少两年)includeSubDomainspreload
错误五:浏览器已经记住旧 max-age,改了配置不生效
HSTS 是浏览器端的机制。一旦浏览器记住了 max-age=31536000,在这 365 天内,即使服务器把 max-age 改小了,浏览器也不会理你。
如果需要紧急回退:
- 把 max-age 设为 0
- 让用户访问一次 HTTP 版本(或者用 Chrome 的
chrome://net-internals/#hsts删除) - 等待旧 max-age 自然过期
相关阅读:Nginx HSTS max-age设置为0会怎样:紧急回退的完整操作指南
错误六:多个 server 块重复设置 max-age,值不一致
如果 Nginx 里有多个 server 块(比如一个处理 HTTP、一个处理 HTTPS),两边 HSTS 的 max-age 值不一样,会导致浏览器行为不一致。
正确做法:HSTS 头只应该在 HTTPS 的 server 块里设置,HTTP 块只做 301 跳转,不设置 HSTS。
# HTTP server 块:只跳转,不设置 HSTS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
# HTTPS server 块:设置 HSTS
server {
listen 443 ssl;
server_name example.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
...
}
如何验证 max-age 是否生效
用 curl 验证:
curl -I https://www.youres.cn 2>/dev/null | grep -i strict
输出应该包含:
strict-transport-security: max-age=31536000; includeSubDomains
也可以用 Chrome 开发者工具 → Network → 点击页面请求 → Headers → Response Headers 查看。
总结
HSTS max-age 的设置看似简单,但细节很多。核心记住几点:单位是秒、别忘了 always 参数、preload 要求两年、浏览器会缓存旧值。按照分阶段方案慢慢来,比一次性配错再救火要省心得多。
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论