hsts在nginx中生效需严格满足四要素:必须置于443 https server块内、add_header指令须带always参数、max-age与includesubdomains需灰度验证、preload为不可逆承诺且需满足全站https等硬性条件。

要在 Nginx 中真正生效 HSTS(HTTP Strict Transport Security),不是简单加一行头就行——它依赖 HTTPS 已稳定运行、配置位置精准、参数严谨且上线节奏可控。
必须放在 443 HTTPS 的 server 块里
HSTS 头只在 HTTPS 响应中被浏览器接受,HTTP(80 端口)响应里设置完全无效,甚至可能引发误用。
- 正确位置:仅写在
listen 443 ssl的 server 块内,且该块已配置ssl_certificate和ssl_certificate_key - 错误做法:写在 80 端口 server 块、http 全局块、或未启用 SSL 的 location 里
- 示例片段:
server {<br> listen 443 ssl http2;<br> server_name example.com;<br> ssl_certificate /path/to/fullchain.pem;<br> ssl_certificate_key /path/to/privkey.pem;<br> add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;<br>}
always 参数不能省略
默认情况下,Nginx 只对 2xx/3xx 响应添加 header。但 404、500、304 等状态码若缺失 HSTS 头,浏览器会中断策略记忆,导致安全链断裂。
- 务必加上
always,确保所有响应(无论状态码)都携带 HSTS 头 - 错误写法:
add_header Strict-Transport-Security "max-age=31536000";(缺 always) - 正确写法:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
max-age 和 includeSubDomains 要分步验证
这两个参数影响范围大,贸然设高或开启子域保护,可能造成用户访问失败且无法回退。
- 先用短周期测试:
max-age=300(5 分钟),确认主站和所有子域 HTTPS 均正常、证书有效、跳转无环 - 逐步延长至
max-age=31536000(1 年) - 启用
includeSubDomains前,确保www、api、cdn等所有一级子域都能独立 HTTPS 访问并返回完整 HSTS 头 - 注意:
includeSubDomains不递归生效,二级子域(如dev.api.example.com)不受保护
preload 是承诺,不是开关
加上 preload 表示你愿意将域名提交到浏览器预加载列表,实现“首次访问即强制 HTTPS”。但它不可逆,撤回需数月。
- 提交前必须同时满足:
– 全站 HTTPS 稳定运行
–max-age ≥ 31536000
– 启用includeSubDomains
– 所有子域响应头含完整 HSTS(含 always) - 验证合规性:用 hstspreload.org 检测
- 提交后等待审核,各主流浏览器会在后续版本中内置该域名











