const jwt = require('jsonwebtoken') const { Admin, User } = require('../models') /** * JWT 认证中间件(管理员) */ const authMiddleware = async (req, res, next) => { try { // 从 header 获取 token const authHeader = req.header('Authorization') if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ success: false, error: '未提供认证令牌' }) } const token = authHeader.replace('Bearer ', '') // 验证 token const decoded = jwt.verify(token, process.env.JWT_SECRET) // 查找管理员 const admin = await Admin.findById(decoded.adminId) if (!admin) { return res.status(401).json({ success: false, error: '管理员不存在' }) } // 检查状态 if (admin.status !== 'active') { return res.status(403).json({ success: false, error: '管理员账户已禁用' }) } // 将管理员信息附加到请求对象 req.admin = admin next() } catch (error) { if (error.name === 'JsonWebTokenError') { return res.status(401).json({ success: false, error: '无效的认证令牌' }) } if (error.name === 'TokenExpiredError') { return res.status(401).json({ success: false, error: '认证令牌已过期' }) } next(error) } } /** * 权限检查中间件 * @param {string} permission - 需要的权限 */ const requirePermission = (permission) => { return (req, res, next) => { if (!req.admin) { return res.status(401).json({ success: false, error: '未认证' }) } if (!req.admin.hasPermission(permission)) { return res.status(403).json({ success: false, error: '权限不足' }) } next() } } /** * 小程序用户 JWT 认证中间件 */ const userAuthMiddleware = async (req, res, next) => { try { const authHeader = req.header('Authorization') if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ success: false, error: '未提供认证令牌' }) } const token = authHeader.replace('Bearer ', '') const decoded = jwt.verify(token, process.env.JWT_SECRET) // 兼容两种token格式:包含userId或openid let user = null if (decoded.userId) { user = await User.findById(decoded.userId).select('+sessionKey') // vpay 签名需要 } else if (decoded.openid) { user = await User.findOne({ openid: decoded.openid }) } if (!user) { return res.status(401).json({ success: false, error: '用户不存在或令牌无效' }) } req.user = user // 优先使用 openid,如果没有则使用 userId 作为标识 req.openid = user.openid || user._id.toString() next() } catch (error) { if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') { return res.status(401).json({ success: false, error: '认证令牌无效或已过期' }) } next(error) } } /** * 可选的用户认证中间件(不强制要求登录) */ const optionalAuthMiddleware = async (req, res, next) => { try { const authHeader = req.header('Authorization') if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.replace('Bearer ', '') const decoded = jwt.verify(token, process.env.JWT_SECRET) const user = await User.findById(decoded.userId) if (user) { req.user = user req.openid = user.openid } } next() } catch (error) { // 即使认证失败也继续,只是不附加用户信息 next() } } module.exports = { authMiddleware, requirePermission, userAuthMiddleware, optionalAuthMiddleware }