50 lines
1.3 KiB
JavaScript
50 lines
1.3 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
||
|
||
/**
|
||
* JWT Token 黑名单(已撤销的 jti 集合)
|
||
*/
|
||
const revokedTokens = new Set();
|
||
|
||
/**
|
||
* 撤销指定 jti 的 token
|
||
*/
|
||
const revokeToken = (jti) => revokedTokens.add(jti);
|
||
module.exports.revokeToken = revokeToken;
|
||
|
||
/**
|
||
* JWT 鉴权中间件
|
||
* 验证请求头中的 Bearer token,写入 req.user
|
||
*/
|
||
const authMiddleware = (req, res, next) => {
|
||
const token = req.headers.authorization?.replace('Bearer ', '');
|
||
if (!token) {
|
||
return res.status(401).json({ success: false, message: '未登录' });
|
||
}
|
||
try {
|
||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||
// 检查 token 是否已撤销
|
||
if (decoded.jti && revokedTokens.has(decoded.jti)) {
|
||
return res.status(401).json({ success: false, message: 'token已失效' });
|
||
}
|
||
req.user = decoded;
|
||
next();
|
||
} catch (err) {
|
||
return res.status(401).json({ success: false, message: 'token无效或已过期' });
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 角色鉴权中间件工厂
|
||
* 用法: requireRole('admin', 'store')
|
||
*/
|
||
const requireRole = (...roles) => {
|
||
return (req, res, next) => {
|
||
if (!roles.includes(req.user?.role)) {
|
||
return res.status(403).json({ success: false, message: '权限不足' });
|
||
}
|
||
next();
|
||
};
|
||
};
|
||
|
||
module.exports = { authMiddleware, requireRole };
|