JWT 的使用场景
- 身份验证:用户登录后,服务器生成一个 JWT 并返回给客户端。客户端在后续请求中发送该 JWT,服务器通过解析 JWT 确认用户身份。
- 信息传递:JWT 可以携带自定义信息,并通过数字签名保证其安全性,适合在不同服务之间传递数据。
JWT 的结构
一个典型的 JWT 长这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImpvaG5kb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.sflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- 头部 (Header):指定加密算法,通常是 HMAC SHA256 或 RSA。
- 载荷 (Payload):包含用户信息和声明 (claims),如用户名、用户 ID、过期时间等。
- 签名 (Signature):通过头部和载荷进行加密,用于确保数据没有被篡改。
在 Node.js 中使用 JWT
使用 jsonwebtoken 库可以方便地在 Node.js 中生成和验证 JWT。
1. 安装 jsonwebtoken:
npm install jsonwebtoken
2. 生成 JWT:
const jwt = require('jsonwebtoken');
// 创建一个 JWT,传入用户信息并设置密钥
const token = jwt.sign({ username: 'johndoe' }, 'your-secret-key', { expiresIn: '1h' });
console.log(token); // 打印生成的 token
sign方法的参数包括:用户信息(载荷)、密钥、以及可选的过期时间等配置。
3. 验证 JWT:
const jwt = require('jsonwebtoken');
// 验证客户端传递过来的 JWT
const token = 'eyJhbGciOiJIUzI1NiIsInR...'; // 客户端传来的 JWT
jwt.verify(token, 'your-secret-key', (err, decoded) => {
if (err) {
console.error('Token 验证失败:', err);
} else {
console.log('Token 验证成功,用户信息:', decoded);
}
});
verify方法接受三个参数:JWT、密钥、回调函数。通过回调函数可以获取验证后的解码信息或错误。
4. 设置过期时间:
JWT 支持设置过期时间,常用的方式是通过 expiresIn 参数指定过期时间。
// 生成一个过期时间为 1 小时的 token
const token = jwt.sign({ username: 'johndoe' }, 'your-secret-key', { expiresIn: '1h' });
使用场景示例:用户登录验证
以下是一个简单的登录示例,用户成功登录后生成并返回 JWT,后续请求中使用该 JWT 验证身份。
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
const users = [
{ id: 1, username: 'johndoe', password: 'password123' }
];
// 登录接口
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (user) {
// 用户验证通过,生成 JWT
const token = jwt.sign({ id: user.id, username: user.username }, 'your-secret-key', { expiresIn: '1h' });
res.json({ token });
} else {
res.status(401).send('用户名或密码错误');
}
});
// 受保护的路由
app.get('/protected', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(403).send('Token 缺失');
}
// 验证 token
jwt.verify(token, 'your-secret-key', (err, decoded) => {
if (err) {
return res.status(401).send('无效的 token');
} else {
res.json({ message: '成功访问受保护的路由', user: decoded });
}
});
});
app.listen(3000, () => {
console.log('服务器启动,监听端口 3000');
});
常见问题:
-
JWT 如何保存?
- 前端通常将 JWT 保存在
localStorage或sessionStorage中,也可以放在 HTTP Cookie 中。
- 前端通常将 JWT 保存在
-
JWT 的安全性?
- 确保使用强加密算法,如
HS256或RS256。 - 避免将敏感信息(如密码)存放在 JWT 中。
- 使用 HTTPS 传输 JWT,防止中间人攻击。
- 确保使用强加密算法,如
-
JWT 的续签机制?
- 使用刷新令牌(refresh token)机制,可以在 JWT 过期后为用户重新生成一个新的 JWT。