nginx中配置hsts必须在443端口https server块内添加add_header strict-transport-security "max-age=31536000; includesubdomains; preload" always;,禁用http端口、确保子域全https、灰度验证后再全量启用。

在 Nginx 的 server 块中配置 Strict-Transport-Security(HSTS)响应头,核心是确保它只出现在 HTTPS 上下文中,并带正确参数和修饰符。
必须放在 HTTPS server 块内
HSTS 头仅在加密连接下被浏览器接受。配置需紧贴 SSL 设置,与 listen 443 ssl 同属一个 server 块:
- ✅ 正确:写在启用 HTTPS 的
server { listen 443 ssl; ... }内部,位置在证书配置之后、location之前均可 - ❌ 错误:写在
http { }全局块或listen 80的 HTTP server 中——前者会导致非 HTTPS 站点误发该头,后者浏览器直接忽略
关键参数要配齐且审慎启用
基础值应包含有效期、子域覆盖与预加载意向,但每项都需匹配实际部署状态:
-
max-age=31536000:设为 1 年(31536000 秒),是稳定防护的最低推荐值 -
includeSubDomains:启用前确认所有一级子域(如api.example.com、cdn.example.com)已部署有效 HTTPS 且可正常响应 200 -
preload:表示你计划提交至浏览器 HSTS 预加载列表(hstspreload.org),启用后不可快速撤回,须满足全站 HTTPS + 子域 HTTPS + max-age ≥ 31536000 + 无 HTTP 回退入口
always 参数不能省略
默认情况下,add_header 只对 2xx 成功响应生效。错误页(404/500)、重定向(301/302)若不携带 HSTS,策略就会中断,长期可能导致浏览器丢弃该策略:
- ❌
add_header Strict-Transport-Security "max-age=31536000";→ 404 页面不发头,策略失效 - ✅
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;→ 所有状态码都携带
上线前建议分阶段验证
避免一次性启用高风险参数导致大面积访问失败:
- 先用
max-age=300(5 分钟)测试,确认主站及各子域无证书错误、跳转循环或混合内容警告 - 观察日志和浏览器开发者工具的响应头是否稳定出现
- 确认 CDN(如 Cloudflare)未过滤或覆盖该头;部分 CDN 默认不透传自定义 header,需单独开启透传设置











