nginx中开启hsts需在443端口https server块内配置add_header strict-transport-security "max-age=31536000; includesubdomains" always;,禁用http端口及全局配置,配合有效证书、301跳转与子域https支持。

在 Nginx 中开启 HSTS,本质是让浏览器“记住”只用 HTTPS 访问你的域名,从而跳过首次 HTTP 请求这个最易被劫持的环节。它不是跳转指令,而是一把“记忆型安全锁”。配置本身简单,但参数、位置和节奏稍有偏差,就可能导致子域无法访问、测试环境被永久拦截,甚至上线后难以回退。
必须放在 443 端口的 HTTPS server 块中
HSTS 头只在加密连接下生效,浏览器会直接忽略 HTTP(80 端口)响应中的该头。如果错加在 http 块或 80 端口 server 中,等于没配。
- 正确做法:只在
server { listen 443 ssl; ... }块内添加 - 禁止在全局 http 块、location 块顶层或 80 端口 server 中写 add_header
- 若使用反向代理(如后端是 Spring Boot 或 Node.js),需屏蔽后端返回的 HSTS 头:
proxy_hide_header Strict-Transport-Security;
add_header 指令必须带 always 参数
不加 always,Nginx 默认只在 2xx 响应中发送该头。一旦遇到 404、500、304 等状态,HSTS 就中断传递,策略可能失效或被浏览器丢弃。
- 标准写法:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - preload 是可选标记,仅在满足预加载条件并准备提交至 hstspreload.org 时启用
- includeSubDomains 表示所有一级子域(如 api.example.com、shop.example.com)都必须已支持 HTTPS 且证书有效
上线前务必灰度验证,别一上来就设一年
max-age 设太大,出问题后用户端无法快速清除(只能等过期或手动清理浏览器 HSTS 缓存)。生产环境推荐从短周期起步。
- 首次部署建议用
max-age=300(5 分钟),观察 15 分钟以上 - 确认无证书错误、混合内容、子域不可达、跳转异常等问题后再逐步延长
- 用
curl -I https://example.com检查响应头是否含预期值,注意看 status 是否为 200 - Chrome 地址栏输 http:// 会直接拦截不发包,验证跳转逻辑请用隐身窗口或 curl
配套基础必须稳固,否则 HSTS 反成障碍
HSTS 不是“补丁”,而是 HTTPS 安全闭环的最后一步。它依赖前置条件全部就绪。
- SSL 证书必须有效、受信,且覆盖所有
server_name声明的域名(包括 www 和裸域) - 80 端口必须配置 clean 的 301 跳转:
return 301 https://$host$request_uri;,禁用 rewrite - 所有子域名需能独立 HTTPS 访问,且响应头中也含一致的 HSTS 策略(若启用 includeSubDomains)
- 若使用 CDN(如 Cloudflare),确认其透传 Strict-Transport-Security 头,部分需后台单独开启











