jsonwebtoken (Node.js)JWT 库
错误信息
jwt signature is required
jsonwebtoken (Node.js) — JsonWebTokenError from jwt.verify()
含义
令牌的第三段是空的——它要么是不受保护的 JWT(`alg: "none"`),要么是签名被截掉的已签名令牌——但你调用 `verify()` 时传入了密钥,因此签名是必需的。jsonwebtoken 会拒绝该令牌,而不是接受无人签名的声明。如果这类令牌从外部到达你的 API,可能有人在试探经典的“alg none”弱点。
原因
alg 为“none”的不受保护令牌
常见RFC 7519 允许在完整性已由其他方式保证的场景中使用未签名的 JWT;API 永远不属于这种场景。像 `eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiJ9.` 这样的令牌可以声称任意身份。
测试或工具中手工构造的令牌
偶见通过对头部和载荷做 base64 编码拼成的测试夹具,或者关闭签名后由调试工具生成的令牌,签名都是空的。
签名在传输途中被去掉了
偶见日志脱敏程序、URL 长度限制或存储列在第二个点之后截断了令牌,留下看似有效的头部和载荷,却没有任何可供验证的内容。
修复方法
- 1.
保留拒绝行为和算法允许列表
验证时使用显式的 `algorithms` 列表,只列出你的颁发者实际使用的算法。如果有未签名的令牌从外部到达,记录请求来源;不要添加接受这类令牌的代码路径。
js // Always pass an explicit allow-list; "none" must never be in it. const claims = jwt.verify(token, publicKey, { algorithms: ["ES256"] }); - 2.
用一次性密钥为测试令牌签名
在测试初始化时生成密钥对,并用它为测试夹具签名,这样测试走的就是与生产环境相同的验证路径。
js import { generateKeyPairSync } from "node:crypto"; // Test setup: a throwaway key pair, real signatures, same verification path as production. const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "P-256" }); const token = jwt.sign({ sub: "test-user" }, privateKey, { algorithm: "ES256", expiresIn: "5m" });