企业级HSTS部署需分阶段验证、严格设max-age≥31536000、谨慎启用includeSubDomains、preload须经hstspreload.org审核,且仅HTTPS响应有效;禁用后不立即失效,须等待过期或手动清除缓存。

企业级网站的 HSTS 部署不能只加一行 add_header Strict-Transport-Security 就算完成。它本质是浏览器端的“强制契约”,一旦生效就绕过服务端控制,配置失误会导致子域名不可访问、调试困难、甚至业务中断。规范化的部署必须兼顾安全性、可逆性、覆盖范围和兼容性。
基础参数必须满足最小安全阈值
HSTS 响应头中三个关键参数需严格设定:
- max-age 至少设为 31536000(1年):低于 6 个月的值无法通过主流浏览器 preload 列表审核,也起不到实质防护作用;太短(如 300 秒)等同于未启用
- includeSubDomains 谨慎启用:仅在全部子域名(含 api、static、admin 等)均已稳定运行 HTTPS 且证书有效时才添加;否则任意一个子域证书异常或配置缺失,将导致整个子域树被浏览器拒绝访问
-
preload 参数不直接配置在 Nginx 中:该标记仅表示“我愿意申请加入浏览器内置 HSTS 列表”,需单独提交至 hstspreload.org 审核;Nginx 中写入
preload仅是前置条件,不是生效动作
必须配合 HTTPS 强制跳转与协议栈加固
HSTS 不替代 HTTP→HTTPS 的 301 跳转,而是补充其短板。二者需协同部署:
- 80 端口只做
return 301 https://$host$request_uri;,不承载任何业务逻辑或静态资源 - 443 端口必须启用
http2并禁用 TLSv1.0/v1.1:ssl_protocols TLSv1.2 TLSv1.3; - 响应头需在 HTTPS server 块内添加,且不能出现在 HTTP server 块或 location 块中(避免被覆盖或遗漏)
- 若使用 CDN 或反向代理(如 DCDN、ESA),HSTS 头必须由最外层边缘节点下发,后端 Nginx 仅作为兜底
上线前必须执行渐进式验证流程
直接上线 full HSTS 极易引发故障。推荐分三阶段推进:
-
第一阶段(监控期):设置
max-age=300+includeSubDomains,观察日志中是否出现子域 HTTP 请求被自动升级失败的情况 -
第二阶段(过渡期):提升至
max-age=31536000,但暂不加preload,持续监测 7 天以上所有子域 HTTPS 可用性与证书续期状态 -
第三阶段(预加载申请):确认无误后,前往 hstspreload.org 提交域名;审核通过后,再在 Nginx 中加入
preload参数(即使提前写了也不影响审核)
规避常见陷阱与副作用
很多故障源于对 HSTS 行为机制理解偏差:
- 不要在 HTTP 响应中加 HSTS 头:RFC 明确规定该头仅在 HTTPS 响应中有效,HTTP 响应中设置会被浏览器忽略
- 禁用 HSTS 后不会立即失效:浏览器仍会按原 max-age 缓存策略执行,只能等待过期或手动清除浏览器 HSTS 缓存(chrome://net-internals/#hsts)
- 跨域调用需注意协议一致性:若前端页面是 HTTP,而后端接口返回了 HSTS 头,浏览器会自动将请求升为 HTTPS,导致 Origin 变更,触发 CORS 拦截;此时应在网关层过滤掉非主站域名的 HSTS 响应头
- 私有 IP 或 localhost 不适用 HSTS:该策略仅对域名生效,对 IP 地址或本地开发域名(如 dev.local)无效,测试环境建议用真实二级域名


















