最稳妥的HSTS启用方式是在443端口HTTPS server块中使用add_header指令并带always参数,配置max-age、includeSubDomains和preload,且必须确保全站HTTPS可用并已配置HTTP→HTTPS跳转。

直接在 Nginx 的 server 块中用 add_header 注入 HSTS 策略,是让浏览器持久化 HTTPS 访问最有效的方式。但必须满足三个硬性前提:只在 443 端口的 HTTPS 服务块中配置、带 always 参数、全站已稳定运行 HTTPS 并完成 HTTP→HTTPS 跳转。
必须放在 HTTPS server 块里,不能写在 80 端口或 http 全局块
HSTS 头只有在加密响应中才被浏览器接受,HTTP 响应里的 Strict-Transport-Security 会被直接忽略。RFC 6797 明确规定了这一点。
- ✅ 正确位置:监听
443 ssl的server块内,且该块已正确加载证书 - ❌ 错误位置:监听 80 的重定向块、
http块顶层、或任何未启用 SSL 的上下文 - ⚠️ 注意:如果用了 CDN(如 Cloudflare),需确认它未屏蔽或覆盖该 header;部分 CDN 需单独开启 HSTS 开关
add\_header 指令必须带 always 参数
默认情况下,Nginx 只在 2xx 成功响应中发送 add_header。但用户可能访问不存在的路径(404)、触发重定向(301/302)或遇到服务器错误(500),这些响应若不带 HSTS 头,就会导致策略“断连”。
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;- 漏掉
always是常见失效原因——检查 F12 Network 中 404 或 302 响应的 Response Headers 是否仍含该头 - 别和 Apache 的
Header always set混淆:Nginx 没有Header指令,写错会导致nginx -t报错
参数组合要兼顾安全与可回退性
上线前不建议一步到位设为一年并启用 preload,尤其当子域名尚未全部 HTTPS 化时。
- 先用短周期测试:
max-age=300(5 分钟),观察半天,确认主站和所有子域名无混合内容、证书错误或跳转异常 -
includeSubDomains启用前,逐个验证子域名能否通过 HTTPS 正常响应(curl -I https://api.example.com) -
preload是不可逆操作:提交到浏览器预加载列表后,即使撤下配置,生效期内也无法解除;仅在满足 hstspreload.org 所有要求后再启用
验证是否真正生效
配置 reload 后,不能只看首页响应头,还要模拟真实访问路径。
- 用
curl -I https://yourdomain.com查看响应头是否含完整 HSTS 字段 - 打开 Chrome,访问一次 HTTPS 页面后,在地址栏输入
http://yourdomain.com—— 若自动变成https://并发起请求(Network 中显示 307 Internal Redirect),说明浏览器已缓存并执行 HSTS - 访问子域名(如
https://www.example.com)并重复上述步骤,确认includeSubDomains生效 - 用
chrome://net-internals/#hsts查询域名是否已被本地记录或预加载


















