JWT(JSON Web Token)在 Node.js 中的加密与解密机制以及过期判断
目录
一、JWT结构
二、Node.js 加解密(验证)JWT
2.1 安装库
2.2 生成 Token(签名)
2.3 解密(验证)Token
2.4 支持的算法列表
过期时间判断机制
三、常见场景代码
3.1 Express 中间件验证
3.2 前端加入Bearer时的处理方式
四、安全建议
一、JWT结构
JWT 是签名(签名验证),由三部分组成:
Header.Payload.SignatureHeader:
编码:这个 JSON 对象会被Base64Url编码,形成 JWT 的第一部分字符串。
{ "alg": "HS256", "typ": "JWT" }Payload:传递的数据(Claims),存放实际要传输的信息。
{ userId: 12345, username: 'testuser' }编码:这个 JSON 对象也会被Base64Url编码,形成 JWT 的第二部分字符串。
⚠️极度重要提示:
Payload 是不加密的!只是进行了 Base64 编码。任何人拿到 Token 都可以解码看到 Payload 里的内容。
千万不要在 Payload 里放密码、手机号等敏感信息
Signature:
作用:安全验证,防止 Token 被篡改。
这一部分是你看不懂的乱码,它是通过前面两部分计算出来的。
生成逻辑:
它需要使用:
- 编码后的 Header
- 编码后的 Payload
- 一个服务器持有的密钥 (secret)
- Header 中指定的算法 (如 HMAC SHA256)
最后,系统将这三部分用 . 连起来,就生成了最终的 Token:
encodedHeader.encodedPayload.signature
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMzQ1LCJleHAiOjE3MzM5NzAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c三部分详解:
部分 | 内容 | 编码方式 |
Header | 算法和类型 | Base64Url |
Payload | 数据(含过期时间) | Base64Url |
Signature | 签名(防篡改) | HMAC-SHA256 |
二、Node.js 加解密(验证)JWT
2.1 安装库
npm install jsonwebtoken2.2 生成 Token(签名)
const jwt = require('jsonwebtoken'); const SECRET_KEY = 'your-secret-key'; // 密钥(妥善保管) // 生成 token const token = jwt.sign( { userId: 12345, username: 'testuser' }, SECRET_KEY, { expiresIn: '2h', // 2小时后过期 algorithm: 'HS512' // <--- 在这里修改算法,指定使用 HMAC SHA-512 } ); console.log(token);Payload 中自动添加的字段:
iat(issued at):签发时间戳exp(expiration):过期时间戳
2.3 解密(验证)Token
const jwt = require('jsonwebtoken'); const SECRET_KEY = 'your-secret-key'; const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; try { // 解密并验证(会自动检查过期时间) const decoded = jwt.verify(token, SECRET_KEY); console.log('解密成功:', decoded); /* 输出: { userId: 12345, username: 'testuser', iat: 1733966579, // 签发时间 exp: 1733973779 // 过期时间 } */ } catch (err) { if (err.name === 'TokenExpiredError') { console.log('Token 已过期'); console.log('过期时间:', err.expiredAt); } else if (err.name === 'JsonWebTokenError') { console.log('Token 无效(签名错误或格式错误)'); } else { console.log('验证失败:', err.message); } }2.4 支持的算法列表
在 Node.js 的 jsonwebtoken 库中,常见的支持算法包括:
算法类型 | 算法名称 | 说明 | 密钥要求 |
HMAC (对称) | HS256 | HMAC using SHA-256 (默认) | 字符串 / Buffer |
HS384 | HMAC using SHA-384 | 字符串 / Buffer | |
HS512 | HMAC using SHA-512 | 字符串 / Buffer | |
RSA (非对称) | RS256 | RSASSA-PKCS1-v1_5 using SHA-256 | 私钥签名 / 公钥验证 |
RS384 | ... SHA-384 | 私钥 / 公钥 | |
RS512 | ... SHA-512 | 私钥 / 公钥 | |
ECDSA (非对称) | ES256 | ECDSA using P-256 and SHA-256 | 私钥 / 公钥 |
过期时间判断机制
jwt.verify()会自动检查过期时间,无需手动判断:
jwt.verify(token, SECRET_KEY); // 过期会抛出 TokenExpiredError三、常见场景代码
3.1 Express 中间件验证
const jwt = require('jsonwebtoken'); const SECRET_KEY = 'your-secret-key'; function authenticateToken(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN if (!token) { return res.status(401).json({ error: '缺少 token' }); } try { const user = jwt.verify(token, SECRET_KEY); req.user = user; // 将用户信息挂载到 request next(); } catch (err) { if (err.name === 'TokenExpiredError') { return res.status(401).json({ error: 'Token 已过期' }); } return res.status(403).json({ error: 'Token 无效' }); } } // 使用 app.get('/protected', authenticateToken, (req, res) => { res.json({ message: '访问成功', user: req.user }); });3.2 前端发送Bearer Token时的处理方式
前端发送 Bearer Token时,后端必须去掉Bearer前缀才能解析 Token
// 前端请求 headers: { 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' }后端接收到的完整字符串是:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...而 jwt.verify() 只能解析纯 Token(不含 Bearer ),所以必须先提取。
nodejs提取处理方式
const jwt = require('jsonwebtoken'); function authenticateToken(req, res, next) { // 1. 获取 Authorization 头 const authHeader = req.headers['authorization']; if (!authHeader) { return res.status(401).json({ error: '缺少 Authorization 头' }); } // 2. 提取 Token(去掉 "Bearer " 前缀) const token = authHeader.split(' ')[1]; // 分割后取第二部分 if (!token) { return res.status(401).json({ error: 'Token 格式错误' }); } // 3. 验证 Token try { const decoded = jwt.verify(token, SECRET_KEY); req.user = decoded; next(); } catch (err) { return res.status(403).json({ error: 'Token 无效或已过期' }); } }四、安全建议
- 密钥安全:
SECRET_KEY必须保密,不要提交到代码仓库 - HTTPS 传输:防止 token 被中间人截获
- 过期时间:敏感操作用短过期(15分钟),长期登录用 Refresh Token
- 不存敏感数据:Payload 可被 Base64 解码,不要放密码等敏感信息