JWT实战避坑:12个开源项目里翻车的6个共同问题

极客阿强 中级 5小时前 更新于 2026年7月25日 382 浏览 6 点赞 约 2 分钟

很多开发者写JWT(JSON Web Token)的时候习惯直接复制教程里的Demo,结果把安全隐患也一起copy进去了。我之前翻了12个Node.js开源项目,从几千星的模板到公司实际在用的脚手架,发现大家踩的坑惊人地一致。

这些项目代码质量其实不错,但JWT这块细节太容易被忽视。分享几个最典型的实操错误,大家对号入座检查下自己的代码。

一、把 "secret" 当成了真正的密钥
这是最离谱的。我在三个项目里直接看到了这样的写法:

const token = jwt.sign({ userId: user.id }, "secret", { expiresIn: "1h" });
这种6位字符的密钥熵值极低,大概只有42 bits。用GPU跑个字典攻击,毫秒级就能破解。记住,教程里的 "secret" 只是占位符。一个合格的256位随机密钥才是生产环境的底线。

二、在鉴权中间件里误用 jwt.decode()
很多同学分不清 decodeverify 的区别。我在一个生产环境的中间件里看到这种写法:

// 极其危险:仅解码,不验证签名
const decoded = jwt.decode(req.headers.authorization.split(" ")[1]);
if (!decoded.userId) return res.status(401).send("Unauthorized");
jwt.decode() 只是把 Base64 编码的 payload 还原成 JSON,它根本不去检查签名是否正确。这意味着攻击者随便伪造一个 payload,只要格式对,就能绕过验证。

正确做法: 必须用 jwt.verify()

const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ["HS256"] });

三、verify() 时没指定算法
即便用了 verify(),如果没写 { algorithms: ['HS256'] },很多库会默认信任 Token 头部(Header)里声明的算法。
如果攻击者把算法改成 alg: none 并把签名部分删掉,某些版本的库会直接判定为合法。所以,显式指定算法是必须的。

四、密钥直接 commit 到 Git 仓库
在某个 config.js 里我看到了这种操作:

module.exports = {
 jwtSecret: "productionsecretdonotshare2024", // 开发者还特意标注了不要分享
 database: process.env.DATABASE_URL
};
只要进入了 Git 历史记录,这个密钥就永久失效了。即便你后来删了这行代码,通过 git log 依然能找回来。一旦泄露,必须立即更换(Rotate)密钥。

五、前端把 Token 存在 localStorage
这是前端开发最常见的习惯:

localStorage.setItem("token", response.data.token);
localStorage 对页面上所有 JS 脚本都是可见的。如果项目里有一个 XSS 漏洞(比如某个评论区没做转义,或者引入的第三方 npm 包有后门),Token 会瞬间被窃取。
进阶方案: 使用 httpOnly 的 Cookie。这种 Cookie 在 JS 层面不可见,能从根源上防御 XSS 窃取 Token。

六、Token 永不过期
很多代码在 sign 的时候漏掉了 expiresIn 参数:

const token = jwt.sign({ userId: user.id }, secret);
没有 exp 声明的 Token 除非手动吊销(而 JWT 很难吊销),否则永远有效。一旦泄露到日志或缓存里,攻击者就拿到了永久通行证。
实战建议: Access Token 设为 15 分钟,需要长会话的话,请部署一套 Refresh Token 机制。

最后给个简单的 Pre-ship 检查清单,上线前对照一下:

  • 密钥强度: 是否通过 CSPRNG 生成且至少 256 bits?
  • 存储位置: 密钥是否在 .env 环境变量中,而非代码里?
  • 验证逻辑: 全局是否禁用了 jwt.decode(),统一使用 jwt.verify()
  • 算法限制: verify 时是否显式传入了 { algorithms: ['HS256'] }
  • 过期策略: 每个 Token 是否都带了合理的 exp 时间?
AI编程AI编程实战webdevsecurityjwtsecret

全部回复 (2)

夜猫子创业者 专家 10小时前
那要是密钥不小心传到Git上了,除了赶紧改掉还能怎么补救?
0 回复
小Kevin在路上 中级 10小时前
确实,我刚入行时直接把密钥写死在代码里,结果被同事一眼看穿。
0 回复

发表回复

支持 Markdown 格式