Token(令牌)是现代 Web 应用中常用的身份验证机制,相比传统的 Session 认证更加灵活和安全。下面我将详细介绍在 Node.js 中实现 Token 认证的完整方案。
Token 认证是一种无状态的认证机制,服务器在用户登录后生成一个加密的字符串(Token)返回给客户端,客户端在后续请求中携带这个 Token 来证明身份。
npm install jsonwebtoken
const jwt = require('jsonwebtoken');
const secret = 'your-secret-key'; // 应该使用环境变量存储
function generateToken(user) {
return jwt.sign(
{
userId: user.id,
username: user.username,
role: user.role
},
secret,
{ expiresIn: '1h' } // Token有效期1小时
);
}
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) return res.sendStatus(401); // 未提供Token
jwt.verify(token, secret, (err, user) => {
if (err) return res.sendStatus(403); // Token无效或过期
req.user = user;
next();
});
}
const express = require('express');
const app = express();
app.use(express.json());
// 模拟用户数据
const users = [
{ id: 1, username: 'admin', password: 'admin123', role: 'admin' },
{ id: 2, username: 'user', password: 'user123', role: 'user' }
];
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 查找用户
const user = users.find(u =>
u.username === username && u.password === password
);
if (!user) {
return res.status(401).json({ error: '用户名或密码错误' });
}
// 生成Token
const token = generateToken(user);
res.json({
message: '登录成功',
token,
user: {
id: user.id,
username: user.username,
role: user.role
}
});
});
app.get('/protected', authenticateToken, (req, res) => {
res.json({
message: '这是受保护的内容',
user: req.user
});
});
安全措施 | 实现方式 | 重要性 |
---|---|---|
使用 HTTPS | 部署 SSL 证书 | ★★★★★ |
设置合理有效期 | expiresIn 参数 |
★★★★☆ |
使用强密钥 | 复杂密钥,定期更换 | ★★★★★ |
存储安全 | 前端使用 HttpOnly Cookie | ★★★★☆ |
黑名单机制 | 注销的 Token 加入黑名单 | ★★★☆☆ |
// 生成刷新Token
function generateRefreshToken(user) {
return jwt.sign(
{ userId: user.id },
secret + 'refresh', // 使用不同的密钥
{ expiresIn: '7d' } // 较长有效期
);
}
// 刷新Token接口
app.post('/refresh-token', (req, res) => {
const { refreshToken } = req.body;
jwt.verify(refreshToken, secret + 'refresh', (err, payload) => {
if (err) return res.sendStatus(403);
const user = users.find(u => u.id === payload.userId);
if (!user) return res.sendStatus(404);
const newToken = generateToken(user);
res.json({ token: newToken });
});
});
JWT 本身是无状态的,要实现注销可以考虑:
即使使用 Token 也需要注意 CSRF 防护:
通过以上实现,您可以在 Node.js 应用中构建一个安全、高效的 Token 认证系统。