不只是字符串拼接
header.payload.signature:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiMDAxIiwidXNlcm5hbWUiOiJhZG1pbiJ9LCJpYXQiOjE3NTMyNTYxOTcsImV4cCI6MTc1MzI1NjI4M30.9FQwcZLyJSyrOj6vJkYho8uFIDgCU23C2B5pvEoMTjM
- Header:指定算法与类型(如
HS256+JWT),决定签名生成方式 - Payload:携带业务数据(如用户ID)和标准声明(
iat签发时间/exp过期时间) - Signature:防伪核心,通过密钥对前两部分加密生成唯一指纹
Header/Payload 仅做 Base64Url 编码(非加密),敏感数据需额外处理!
header、payload、signature转译:
Signature 签名
signature:算法+密钥对编码后的header和payload进行签名,对结果进行base64编码的结果
const crypto = require('crypto');
// 1. 准备原始数据
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
const payload = Buffer.from(JSON.stringify({ user: { id: '001' } })).toString('base64url');
// 2. 生成签名核心操作
const signature = crypto.createHmac('sha256', '你的密钥')
.update(`${header}.${payload}`)
.digest('base64url');
通过 HMAC-SHA256 将密钥与编码后的头部、载荷绑定,任何字符修改都会导致签名失效
本质:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
验证过程:
const jwt = require('jsonwebtoken');
// 验证场景
const fakeToken = 'eyJhbG...改动的部分.MTIzNDU2';
try {
const decoded = jwt.verify(fakeToken, '你的密钥');
console.log('验证通过');
} catch (err) {
console.log('攻击拦截!原因:', err.message);
// 典型错误:invalid signature / expired token
}
验证机制:
- 分离 Token 的三段数据
- 用相同算法+密钥重新计算签名
- 比对计算结果与传入的 Signature 是否完全一致
安全陷阱
-
密钥管理
- 弱密钥(如
"secret")可直接暴力破解 - 解决方案:使用环境变量存储,定期轮换
- 弱密钥(如
-
算法欺骗攻击
- 篡改 Header 中的
alg为none绕过验证 - 防御:代码中显式指定算法
jwt.verify(token, key, { algorithms: ['HS256'] })
- 篡改 Header 中的
-
数据泄露风险
- Payload 内容可被 Base64 解码直接查看
// 攻击者控制台操作 atob('eyJ1c2VyIjp7ImlkIjoiMDAxIiwidXNlcm5hbWUiOiJhZG1pbiJ9'); // 输出:{"user":{"id":"001","username":"admin"}}- 敏感数据(如密码)必须加密后存储
实践
// 安全增强版实现
const token = jwt.sign(
{
user: { id: '001' },
// 自动注入标准声明
},
process.env.JWT_SECRET,
{
algorithm: 'HS256',
expiresIn: '2h', // 强制过期时间
header: { kid: '密钥ID' } // 支持密钥轮换
}
);
// 解密时验证声明有效性
jwt.verify(token, getKeyByKid(kid), {
algorithms: ['HS256'],
clockTolerance: 30, // 允许30秒时钟偏差
ignoreExpiration: false // 强制检查过期
});
工程化要点:
- 密钥与业务分离,使用 KMS 或 Vault 托管
- 携带
kid(Key ID)支持动态密钥更新 - 短期令牌 + Refresh Token 双机制平衡安全与体验
JWT 是防篡改票据而非加密容器,该用 AES 加密的数据别放进 Payload!