Helmet之Strict-Transport-Security实战:如何用HSTS强制HTTPS并正确设置preload
【免费下载链接】helmetHelp secure Express apps with various HTTP headers项目地址: https://gitcode.com/gh_mirrors/he/helmet
在 Express 应用中使用Helmet安全中间件时,Strict-Transport-Security(简称HSTS)是保护用户免受中间人攻击的关键 HTTP 响应头。本文带你用 Helmet 快速启用 HSTS 强制 HTTPS 访问,并讲清maxAge、includeSubDomains、preload三个参数的正确用法,让你一次性配置到位。
一、HSTS 是什么?为什么需要它 🛡️
假设用户第一次访问你的网站时走了不安全的http://链接,攻击者有可能劫持这次通信。HSTS 的作用就是告诉浏览器:
"记住!在未来一段时间内,访问这个域名只能走 HTTPS,直接用 HTTP 的请求一律强制转成 HTTPS。"
一旦浏览器收到并记住了这个头,用户之后即使手滑输入http://example.com,浏览器也会在本地自动改成https://,从根源上杜绝了"首次请求被劫持"的窗口。
需要特别理解一点:HSTS 头本身不完成跳转,它只是让浏览器"记住"域名要强制 HTTPS。对真正访问 HTTP 用户的 301 重定向,通常由反向代理(Nginx 等)配合完成。
二、Helmet 默认帮你开启 HSTS ✅
在 Helmet 中,你什么都不用写,HSTS 头就已经生效了:
app.use(helmet());默认发出的响应头为:
Strict-Transport-Security: max-age=31536000; includeSubDomains含义:记住365 天(31536000 秒),且策略自动覆盖所有子域名。相关实现位于 index.ts,默认值365 * 24 * 60 * 60在 index.ts 中定义。
三、三个关键参数速查表
| 参数 | 类型 | 默认值 | 作用 |
|---|---|---|---|
maxAge | 数字(秒) | 31536000(365天) | 浏览器记住策略的时长,单位是秒不是天 |
includeSubDomains | 布尔 | true | 策略是否扩展到所有子域名 |
preload | 布尔 | false | 声明你有意将站点加入浏览器预加载列表 |
三种常见配置效果对比:
// 1. 基础:自定义时长 // → max-age=123456; includeSubDomains helmet({ strictTransportSecurity: { maxAge: 123456 } }) // 2. 不含子域名 // → max-age=123456 helmet({ strictTransportSecurity: { maxAge: 123456, includeSubDomains: false } }) // 3. 申请预加载 // → max-age=63072000; includeSubDomains; preload helmet({ strictTransportSecurity: { maxAge: 63072000, preload: true } })另外,strictTransportSecurity也有兼容旧版写法的别名hsts,见 index.ts。
四、正确设置 preload 的完整步骤 🚀
开启preload: true是告诉浏览器厂商:"我想被写进各大浏览器的内置 HSTS 预加载列表"。被收录后,即使用户第一次访问你的域名,也直接强制 HTTPS,安全性再上一个台阶。
提交资格硬性要求(缺一不可):
- ✅
maxAge至少为1 年(31536000 秒) - ✅
includeSubDomains必须为true - ✅ 主域名和所有子域名都必须支持 HTTPS
- ✅ 域名必须支持 SNI
推荐配置:
app.use( helmet({ strictTransportSecurity: { maxAge: 31536000, // 至少 1 年 includeSubDomains: true, // 必须开启 preload: true, }, }), );配置完成后,到 hstspreload.org 提交域名即可进入审核队列。更多说明可参考模块内的 README.md。
五、新手最容易踩的 4 个坑 ⚠️
参数名拼错会直接报错。Helmet 做了严格校验(见 index.ts):
- 写成小写
maxage→ 报错提示你应该是maxAge - 写成
includeSubdomains(小写 d)→ 报错提示正确写法是includeSubDomains
这些校验行为在 strict-transport-security.test.ts 中有完整测试覆盖,写错时第一时间就能发现问题,不会静默失效。
- 写成小写
maxAge单位是秒。maxAge: 365只等于约 6 分钟,而不是 365 天。传小数会被向下取整;传负数、NaN、字符串都会抛错。HTTP 明文下该头会被浏览器忽略。所以它不会破坏纯 HTTP 的本地开发调试,但要注意:如果多个本地应用共用
localhost,HSTS 记忆可能引发意外的强制跳转。遇到这种情况可在开发环境关闭该头:helmet({ strictTransportSecurity: false });先确认全站(含所有子域)HTTPS 就绪再开
includeSubDomains。一旦开启,任何一个未配好证书的mail.你的域名都会无法访问——这是"双刃剑",先自查再打开。
六、如何验证配置成功?🔍
- 打开浏览器开发者工具 → Network → 查看任意响应头,确认出现
Strict-Transport-Security - 用
curl -I https://你的域名查看响应头中是否包含预期的max-age与preload指令 - 预加载提交后,在
chrome://net-internals/#hsts中可查询域名是否已入列表
七、小结与延伸阅读
| 场景 | 推荐配置 |
|---|---|
| 快速上线 | 直接用默认(1 年 + 子域名) |
| 提交浏览器预加载 | maxAge ≥ 1年 + includeSubDomains + preload |
| 纯 API 无子域业务 | includeSubDomains: false即可 |
HSTS 是 Helmet 13 个安全响应头中最"一劳永逸"的一个,建议所有面向公网的 Express 应用默认开启。更多配置细节可查看 README.md 中的 HSTS 章节,或浏览 CHANGELOG.md 了解该模块的版本演进。
【免费下载链接】helmetHelp secure Express apps with various HTTP headers项目地址: https://gitcode.com/gh_mirrors/he/helmet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考