nginx启用hsts必须在443端口https server块中配置add_header strict-transport-security "max-age=31536000; includesubdomains; preload" always,搭配80端口301跳转,灰度验证后再上线。

在 Nginx 中启用 HSTS 不是加一行头就完事,关键在于配置位置对、参数合理、范围可控、上线稳妥。它真正起效的前提是:网站已稳定运行 HTTPS,且所有参与的域名都具备有效证书。
必须在 443 端口的 HTTPS server 块中配置
HSTS 头只通过 HTTPS 响应生效,HTTP(80 端口)响应中设置会被浏览器直接忽略。更严重的是,如果错放在 http 或 location 块顶层,可能被覆盖或误作用于非 HTTPS 上下文。
- 正确做法:只在监听
443 ssl的server块内添加 - 务必搭配
always参数,确保 404、500、304 等非 2xx 响应也携带该头,避免策略中断 - 如果后端应用(如 Spring Boot、Node.js)自己返回 HSTS,需在 Nginx 中用
proxy_hide_header Strict-Transport-Security屏蔽,防止冲突
合理设置 max-age 和 includeSubDomains
max-age 决定浏览器强制 HTTPS 的时长,includeSubDomains 则把策略扩展到所有子域——但这是有代价的。
- 首次上线强烈建议从
max-age=300(5 分钟)开始灰度,观察 15 分钟以上:确认无跳转失败、混合内容警告、证书错误 - 只有当主站和全部子域(如
api.example.com、blog.example.com)均能稳定 HTTPS 访问、证书有效,才可启用includeSubDomains - 若任一子域 HTTPS 不可用,用户访问该子域失败后,主域也可能被浏览器标记为“不安全”并拒绝加载
preload 要满足硬性条件且不可逆
加上 preload 是为了提交到浏览器预加载列表,实现“第一次访问即强制 HTTPS”。但这不是开关,而是承诺。
- 必须同时满足:全站 HTTPS、
max-age ≥ 31536000、含includeSubDomains、所有子域响应头中也有完整 HSTS 策略 - 提交前请先访问 hstspreload.org 自检,确认全部通过
- 一旦被收录,撤回需数月甚至半年以上,测试环境切勿启用
配套动作不能少
HSTS 是 HTTPS 安全闭环的一环,单独启用效果有限,需与基础配置协同。
- 80 端口 server 块中必须配置 301 跳转:
return 301 https://$host$request_uri; - 检查 CDN(如 Cloudflare)是否透传
Strict-Transport-Security;默认可能过滤自定义头,需手动开启 - 验证方式:用 curl 或浏览器开发者工具查看响应头,确认
Strict-Transport-Security出现在 443 请求的 Response Headers 中,且值与配置一致











