HSTS 是什么
HSTS(Strict-Transport-Security)让浏览器记住「本站以后只用 HTTPS 访问」。在 max-age 有效期内,即使用户手动输入 http:// 或点到 http 链接,浏览器也会在本地把地址改写成 https 再发出,从根上堵住 SSL 剥离降级攻击。它是浏览器本地策略,服务端无法查询状态,也无法远程撤销。
基本信息
| 名称 | Strict-Transport-Security |
|---|---|
| 作用 | 强制后续访问使用 HTTPS |
| 规范 | RFC 6797 |
| 参数 | max-age=秒;includeSubDomains;preload |
| 生效条件 | 必须通过 HTTPS 响应下发,HTTP 响应里的该头会被忽略 |
| 作用范围 | 单个浏览器实例,清空浏览器状态即失效 |
参数逐项读法
| 参数 | 含义 | 注意点 |
|---|---|---|
| max-age | 记住的秒数,0 表示清除策略 | 一年写作 31536000 |
| includeSubDomains | 所有子域一并对 HTTPS 强制 | 子域没有证书会把用户直接挡在门外 |
| preload | 申请加入浏览器内置列表 | 条件更严格,退出周期长达数月 |
Nginx 配置与灰度
Nginx 配置与灰度
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# always 保证跳转响应与错误响应也带上该头
# 灰度建议:先 max-age=300 观察几天,再逐级加长
# 首次访问仍可能走 HTTP,靠 301 跳转弥补首次降级窗口上线顺序
- 先确认全站与所有子域都有有效证书,http 能正确 301 到 https
- 用短 max-age(如 300 秒)试跑,重点观察混合内容与跳转异常
- 确认无问题后加长到六个月或一年
- 确认子域都已覆盖 HTTPS 后,再加 includeSubDomains
- preload 放在最后一步,并接受「短期内无法回退」的代价
常见问题表现
- 只对 200 响应加头,跳转与错误响应漏掉,留下降级窗口
- 浏览器控制台出现 net::ERR_SSL_PROTOCOL_ERROR 且无法点击继续访问
- 内网系统证书过期后整站无法打开,用户绕不过去
- 用 HTTP 下发该头没有任何效果,看起来像「配置没生效」
max-age 一旦下发,浏览器在该时段内强制 HTTPS 且无法用 HTTP 回退;上线前务必确认全站及子域都具备证书。
验证与演练
- 用 curl -sI 确认响应头里真的出现 Strict-Transport-Security,max-age 与预期一致
- 在地址栏输入 http:// 观察浏览器是否自动改写为 https
- 演练回退路径:先把 max-age 调小并等它过期,再考虑下线 HTTPS
- 上线前后各做一次安全头检查,确认没有引入新的混合内容问题