Files
tech-achievement-management…/server/middleware/auth.js
T
2026-04-19 14:05:40 +08:00

75 lines
2.5 KiB
JavaScript

const jwt = require('jsonwebtoken');
const db = require('../db');
require('dotenv').config();
const verifyToken = async (req, res, next) => {
// 优先从 Header 获取,如果没有则从 Query String 获取(用于下载接口)
const token = req.headers['authorization']?.split(' ')[1] || req.query.token;
if (!token) {
return res.status(401).json({ message: '未提供认证令牌' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// 单点登录检查:比对 Token 中的版本号与数据库中的版本号
// 如果 Token 中没有 version (旧 Token),视为 0
const tokenVersion = decoded.token_version || 0;
const result = await db.query('SELECT token_version FROM users WHERE id = $1', [decoded.id]);
if (result.rows.length === 0) {
return res.status(401).json({ message: '用户不存在' });
}
const dbVersion = result.rows[0].token_version || 0;
if (tokenVersion !== dbVersion) {
return res.status(401).json({ message: '您的账号已在其他设备登录,请重新登录' });
}
req.user = decoded;
next();
} catch (err) {
if (err.name === 'TokenExpiredError') {
return res.status(401).json({ message: '登录已过期,请重新登录' });
}
return res.status(401).json({ message: '无效的令牌' });
}
};
const isAdmin = (req, res, next) => {
if (req.user && (req.user.role === 'admin' || req.user.role === 'super_admin')) {
next();
} else {
return res.status(403).json({ message: '需要管理员权限' });
}
};
const isSuperAdmin = (req, res, next) => {
if (req.user && req.user.role === 'super_admin') {
next();
} else {
return res.status(403).json({ message: '需要超级管理员权限' });
}
};
const isMaintainer = (req, res, next) => {
if (req.user && req.user.role === 'maintainer') {
next();
} else {
return res.status(403).json({ message: '需要系统维护员权限' });
}
};
// 系统管理员权限:超级管理员 OR 系统维护员
const isSystemAdmin = (req, res, next) => {
if (req.user && (req.user.role === 'super_admin' || req.user.role === 'maintainer')) {
next();
} else {
return res.status(403).json({ message: '需要系统管理权限' });
}
};
module.exports = { verifyToken, isAdmin, isSuperAdmin, isMaintainer, isSystemAdmin };