hsts头必须仅配置在listen 443 ssl的server块内,http(80端口)响应中设置会被浏览器直接忽略;需加always参数确保所有状态码响应均携带该头,并配套80端口301跳转及全站https就绪。

必须把 HSTS 响应头只放在监听 443 端口且启用 SSL 的 server 块中,HTTP(80 端口)server 块里加了也无效,浏览器直接忽略——这不是“避免泄露”,而是协议层面的硬性限制。
只在 HTTPS server 块中配置 add_header
HSTS 只能通过安全连接传递,这是浏览器强制要求。Nginx 配置中必须确保:
- 该
add_header Strict-Transport-Security ...指令出现在listen 443 ssl;的 server 块内,不能写在 http 或全局块,也不能错放到 80 端口的 server 中 - 使用
always参数,保证 404、500、304 等非 200 响应也携带该头,防止策略意外中断 - 若后端应用(如 Java、Node.js)自己输出 HSTS 头,需在 Nginx 中用
proxy_hide_header Strict-Transport-Security屏蔽,避免重复或冲突
禁用 HTTP server 中的 HSTS 尝试
有些配置会误把 HSTS 头加到 80 端口块里,比如:
server {
listen 80;
add_header Strict-Transport-Security "max-age=31536000"; ← 浏览器完全无视
return 301 https://$host$request_uri;
}
这种写法不仅无效,还可能造成维护误解。正确做法是:80 端口 server 块只做跳转,不加任何 HSTS 相关头。
验证是否只在 HTTPS 下生效
用 curl 检查两个端口的响应头:
-
curl -I http://example.com→ 不应出现Strict-Transport-Security字样 -
curl -I https://example.com→ 应明确返回该头,且值与配置一致 - 浏览器开发者工具的 Network 标签页中,仅在 443 请求的 Response Headers 里看到该头
配套动作不可省略
HSTS 生效依赖完整 HTTPS 基础:
- 80 端口必须配置 clean 的 301 跳转:
return 301 https://$host$request_uri; - 所有子域(如 api.example.com)都已部署有效证书并能稳定响应 HTTPS
- 若用 CDN(如 Cloudflare),确认其透传
Strict-Transport-Security头,默认可能过滤,需手动开启











