本文目录导读:

HSTS(HTTP Strict Transport Security,HTTP严格传输安全) 是一个非常重要的安全响应头部,用于强制浏览器只能通过 HTTPS 与服务器进行通信,从而有效防范中间人攻击、协议降级攻击和 Cookie 劫持。
以下是关于 HSTS 的详细说明,包括其作用、配置方法、注意事项以及常见问题。
核心作用
当你访问一个网站时,即使你在地址栏输入 http:// 或只输入域名,浏览器也可能会先尝试 HTTP 连接,如果网络环境不安全(如公共 WiFi),攻击者可以拦截这个请求,篡改内容或窃取信息,这就是 SSL 剥离攻击。
HSTS 的作用就是:
- 强制 HTTPS:浏览器一旦收到 HSTS 头部,在有效期内,绝不会再通过 HTTP 发送请求,而是直接在内部将所有 HTTP 链接重写为 HTTPS。
- 拒绝无效证书:如果浏览器遇到证书错误(如过期、自签名、域名不匹配),HSTS 会阻止用户点击“继续访问”的选项,直接显示错误页面,防止用户绕过安全警告。
头部语法
服务器需要在 HTTPS 响应头中包含以下字段:
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload
-
max-age=<seconds>(必选):- 指定浏览器在未来多少秒内必须强制使用 HTTPS。
max-age=31536000表示 1 年(365天)。- 注意:一旦设置,在到期前很难撤销(除非设置为 0)。
-
includeSubDomains(可选,强烈建议):- 告知浏览器该规则也适用于当前域名的所有子域名。
- 如果设置在
example.com,则api.example.com和www.example.com也会被强制执行 HTTPS。 - 风险:如果你的某个子域名不支持 HTTPS(
old-blog.example.com),设置此选项会导致该子域名完全无法访问。
-
preload(可选,用于提交到 HSTS 预加载列表):- 表示允许该域名被提交到浏览器厂商维护的 HSTS 预加载列表。
- 一旦域名被硬编码进浏览器(Chrome、Firefox、Safari 等),用户在第一次访问时就会强制使用 HTTPS,无需等待首次响应头。
如何配置(示例)
Nginx
在 server 块中添加:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Apache
在 .htaccess 或 httpd.conf 中添加:
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
IIS (通过 web.config)
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=63072000; includeSubDomains; preload" />
</customHeaders>
</httpProtocol>
</system.webServer>
Express.js (Node.js)
const helmet = require('helmet');
app.use(helmet.hsts({
maxAge: 63072000,
includeSubDomains: true,
preload: true
}));
HSTS Preload(预加载列表)
问题:普通 HSTS 存在一个“第一次访问”的漏洞,如果用户从未访问过你的 HTTPS 网站,第一次通过 HTTP 请求时,攻击者可以拦截它,阻止浏览器收到 HSTS 头部。
解决方案:向 hstspreload.org 提交你的域名,一旦审核通过,你的域名会被硬编码到 Chrome、Firefox、Safari、Edge 等浏览器的代码中,从此,浏览器在任何情况下都会直接使用 HTTPS 连接你的域名。
⚠️ 警告:
- 提交后难以移除:如果提交后你决定关闭 HTTPS,需要联系浏览器厂商,且可能需要等待数月甚至更久才能从列表中移除。
- 需要满足条件:必须配置
max-age至少为 1 年(31536000秒)、包含includeSubDomains和preload指令,并且所有子域名都必须支持 HTTPS。
安全注意事项与最佳实践
-
仅通过 HTTPS 发送:千万不要在 HTTP 响应中设置 HSTS 头部,因为 HTTP 请求本身就可以被篡改,设置无效。
-
从较低的
max-age开始:如果你是第一次配置,先使用较短的max-age(如 5 分钟300或 1 小时3600),确保没有负面影响后,再逐步增加到半年(15768000)或一年(31536000)。 -
先别加
includeSubDomains:- 确认所有子域名(包括
www、api、mail等)都支持 HTTPS。 - 如果不确定,先不加该选项,或者单独为子域名配置 HSTS。
- 确认所有子域名(包括
-
小心
preload:- 只有在你 100% 确定 再也不会回退到 HTTP 并且所有子域名都准备好时,才提交预加载,一旦提交,撤销极其困难。
-
配合 301 重定向:
确保 HTTP 到 HTTPS 的 301 永久重定向工作正常,否则用户无法从 HTTP 转换到 HTTPS,也就无法获取到 HSTS 头部。
-
使用浏览器检查:
- 打开浏览器开发者工具 (F12) -> 网络 (Network) 标签。
- 点击一个 HTTPS 请求,查看响应头 (Response Headers) 中是否包含
Strict-Transport-Security。
常见问题
Q:为什么我在 HTTP 响应中看不到这个头部? A:因为 HSTS 头部必须在 HTTPS 响应中发送。
Q:如果浏览器时间是错误的怎么办?
A:浏览器会使用本地时间计算 max-age,如果用户时间大幅度跳跃(例如调整到未来),可能导致 HSTS 策略意外过期或提前生效。
Q:如何暂时关闭 HSTS?
A:将 max-age 设置为 0,然后通过 HTTPS 访问一次,浏览器会清除该域名的 HSTS 策略,但如果你提交了 preload,这种方法无效,需要联系浏览器厂商。
Q:设置了 HSTS 后,网站突然打不开了? A:最常见的原因是:
includeSubDomains覆盖了一个不支持 HTTPS 的子域名。- 证书配置错误。
- 用户清除了 HSTS 缓存或时间错乱。
- HSTS 是 HTTPS 的安全补充,而不是替代品。
- 标准实践:
max-age=31536000; includeSubDomains; preload(仅当你有决心时加 preload)。 - 核心作用:彻底消除 HTTP -> HTTPS 重定向过程中的风险,杜绝用户点击 SSL 证书错误提示的可能性。
合理配置 HSTS 是提升网站安全等级的重要一步,尤其是在处理登录、支付等敏感操作时。