hsts不是开启https的开关,而是让浏览器记住只允许https访问,解决首次http请求劫持风险;必须在https已稳定运行前提下,于443端口server块中配置max-age=31536000、includesubdomains和preload,并加always参数确保所有响应携带。

HSTS 不是让网站“开始用 HTTPS”,而是让浏览器“记住只许用 HTTPS”。它解决的是用户首次访问时 HTTP 请求被劫持的风险,必须在 HTTPS 已稳定运行的前提下配置,否则无效甚至有害。
核心参数含义与企业级取值依据
Strict-Transport-Security 响应头由三个关键部分组成,每项都直接影响安全强度和合规性:
- max-age=31536000:有效期设为 1 年(31536000 秒),满足等保三级“HSTS 策略有效期不少于 1 年”的强制要求;低于 31536000 秒可能不通过安全审计
- includeSubDomains:启用后,所有一级子域(如 api.example.com、www.example.com)自动继承 HSTS 策略;但不覆盖二级子域(如 dev.api.example.com),需单独保障其 HTTPS 可用性
- preload:表示申请加入浏览器预加载列表(hstspreload.org),实现“首次访问即 HTTPS”;提交后不可立即撤回,平均下线周期超 3 个月,仅限生产环境全站 HTTPS 零异常运行满 7 天后启用
必须遵守的部署位置与上下文规则
HSTS 头只有在加密通道中被浏览器识别,配置位置错误等于未配置:
- 只允许写在
server { listen 443 ssl; }块内,且该块已正确配置ssl_certificate和ssl_certificate_key - 禁止出现在
listen 80的 server 块、http{}全局块、或任何未启用 SSL 的 location 中 - 禁用条件判断写法,例如
if ($scheme = https) { add_header ... }—— Nginx 官方明确标注行为不可靠,易导致策略漏发
always 参数不可省略的关键原因
默认情况下,Nginx 仅对 2xx/3xx 响应添加 header。若缺失 always,以下场景将丢失 HSTS 头,造成策略中断:
- 静态资源返回 304 Not Modified
- 接口返回 404 或 500 错误页
- 重定向响应(如 302 跳转)
- CDN 回源失败返回的 502/503
正确写法:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
分阶段上线与灰度验证流程
企业环境严禁一次性启用全部高风险参数,推荐按节奏推进:
- 第一阶段(至少 15 分钟):仅配置
max-age=300,验证主站及所有子域 HTTPS 连通性、证书有效性、无混合内容警告 - 第二阶段(持续 24 小时):提升至
max-age=31536000,观察监控平台中 HSTS 相关错误率(如 subdomain 访问失败、证书链中断告警) - 第三阶段(确认无异常后):启用
includeSubDomains,并检查所有子域响应头是否完整携带 HSTS - 最终阶段(全站 HTTPS 稳定运行满 7 天):添加
preload,同步提交至 hstspreload.org
上线前务必屏蔽后端服务(如 Spring Boot、Node.js)自行输出的 HSTS 头,避免与 Nginx 冲突,可使用 proxy_hide_header Strict-Transport-Security; 统一管控。











