HSTS 是什么
HSTS(HTTP Strict Transport Security,RFC 6797)通过一个响应头告诉浏览器:在未来一段时间内只允许用 HTTPS 访问本站(可选覆盖子域)。浏览器会把策略缓存在本地,把站内的 HTTP 链接自动改写为 HTTPS,从而挡住协议降级、中间人剥离 HTTPS 与 Cookie 明文泄漏。
基本信息
| 响应头 | Strict-Transport-Security |
|---|---|
| 常用取值 | max-age=31536000; includeSubDomains |
| max-age | 策略有效期,单位秒;建议从短值验证后再加长 |
| includeSubDomains | 策略是否覆盖全部子域 |
| 生效条件 | 只在 HTTPS 响应中生效,HTTP 响应里的该头被浏览器忽略 |
| 扩展项 | preload 用于申请加入浏览器预加载列表 |
| 排查命令 | curl -sI https://example.com | grep -i strict |
典型使用场景
- 全站强制 HTTPS:与 80 端口跳转配合,防止用户被引导到明文入口
- 防协议降级:首次访问后浏览器不再接受明文连接,挡住剥离攻击
- Cookie 保护:避免会话 Cookie 随明文请求外泄
- 合规整改:多数安全基线把 HSTS 列为必备项
- 子域统一:确认全部子域支持 HTTPS 后用 includeSubDomains 统一收口
nginx 配置示例
nginx 配置示例
# 首次部署建议先用短 max-age 验证,确认无副作用后再放大到一年
add_header Strict-Transport-Security "max-age=300" always;
# 验证通过后的正式配置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 注意:add_header 在存在更内层 add_header 时会被覆盖,location 内需重复声明
检查响应头与跳转
检查响应头与跳转
# 确认 HTTPS 响应里带有 HSTS 头
curl -sI https://example.com | grep -i strict-transport-security
# 确认 HTTP 入口已被 301 跳转,且保留原路径
curl -sI http://example.com/path?a=1 | grep -iE 'HTTP/|location'
# 确认子域也已启用 HTTPS,避免 includeSubDomains 造成不可访问
curl -sI https://www.example.com | head -1参数与生效规则
| 参数 | 含义 | 实践建议 |
|---|---|---|
| max-age | 浏览器记住策略的秒数 | 先 300 秒验证,再逐级放大到一年 |
| includeSubDomains | 策略覆盖全部子域 | 确认所有子域均可 HTTPS 后再启用 |
| preload | 申请加入浏览器预加载列表 | 需先满足预加载要求且不易撤回 |
| 生效位置 | 仅 HTTPS 响应有效 | 确认主站与 API 域名都返回该头 |
| 覆盖问题 | 内层 add_header 会覆盖外层 | 在需要的 location 重复声明或统一在 server 层管理 |
HSTS 具有不可回退性:一旦浏览器缓存了策略,在 max-age 到期前用户无法用 HTTP 访问,也无法通过撤销证书或下架配置立即恢复。而 includeSubDomains 会让策略波及全部子域与内部域名,启用前必须完成资产盘点。
只在 80 端口或部分 location 配置该头没有意义:浏览器只认 HTTPS 响应中的 HSTS。若站点同时存在静态资源域名与 API 域名,应逐个确认它们都返回了同样的策略,否则会出现「主站已强制、子域仍可明文」的割裂状态。