131 lines
3.1 KiB
JavaScript
131 lines
3.1 KiB
JavaScript
|
|
const jwt = require('jsonwebtoken')
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @swagger
|
|||
|
|
* components:
|
|||
|
|
* securitySchemes:
|
|||
|
|
* bearerAuth:
|
|||
|
|
* type: http
|
|||
|
|
* scheme: bearer
|
|||
|
|
* bearerFormat: JWT
|
|||
|
|
* security:
|
|||
|
|
* - bearerAuth: []
|
|||
|
|
* responses:
|
|||
|
|
* UnauthorizedError:
|
|||
|
|
* description: 未授权访问
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: false
|
|||
|
|
* message:
|
|||
|
|
* type: string
|
|||
|
|
* example: 未授权访问
|
|||
|
|
* ForbiddenError:
|
|||
|
|
* description: 权限不足
|
|||
|
|
* content:
|
|||
|
|
* application/json:
|
|||
|
|
* schema:
|
|||
|
|
* type: object
|
|||
|
|
* properties:
|
|||
|
|
* success:
|
|||
|
|
* type: boolean
|
|||
|
|
* example: false
|
|||
|
|
* message:
|
|||
|
|
* type: string
|
|||
|
|
* example: 权限不足
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
// 从环境变量或配置中获取JWT密钥
|
|||
|
|
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* JWT认证中间件
|
|||
|
|
* 验证请求中的JWT token,确认用户身份
|
|||
|
|
* @param {Object} req - Express请求对象
|
|||
|
|
* @param {Object} res - Express响应对象
|
|||
|
|
* @param {Function} next - Express下一个中间件函数
|
|||
|
|
*/
|
|||
|
|
const authenticateJWT = (req, res, next) => {
|
|||
|
|
// 从Authorization头中获取token
|
|||
|
|
const authHeader = req.headers.authorization
|
|||
|
|
|
|||
|
|
if (!authHeader) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '未提供认证令牌'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取token(格式:Bearer <token>)
|
|||
|
|
const token = authHeader.split(' ')[1]
|
|||
|
|
|
|||
|
|
if (!token) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '无效的认证令牌格式'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 验证token
|
|||
|
|
const decoded = jwt.verify(token, JWT_SECRET)
|
|||
|
|
|
|||
|
|
// 将解码的用户信息附加到请求对象中
|
|||
|
|
req.user = decoded
|
|||
|
|
|
|||
|
|
// 继续处理请求
|
|||
|
|
next()
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('JWT验证失败:', error)
|
|||
|
|
|
|||
|
|
if (error.name === 'TokenExpiredError') {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '认证令牌已过期'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '无效的认证令牌'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 用户角色授权中间件
|
|||
|
|
* 检查用户是否具有指定角色
|
|||
|
|
* @param {Array<string>} allowedRoles - 允许访问的角色列表
|
|||
|
|
* @returns {Function} Express中间件函数
|
|||
|
|
*/
|
|||
|
|
const authorizeRoles = (...allowedRoles) => {
|
|||
|
|
return (req, res, next) => {
|
|||
|
|
// 确保用户已通过认证
|
|||
|
|
if (!req.user) {
|
|||
|
|
return res.status(401).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '未授权访问'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查用户角色是否在允许列表中
|
|||
|
|
if (!allowedRoles.includes(req.user.user_type)) {
|
|||
|
|
return res.status(403).json({
|
|||
|
|
success: false,
|
|||
|
|
message: '权限不足'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 用户具有所需角色,继续处理请求
|
|||
|
|
next()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
authenticateJWT,
|
|||
|
|
authorizeRoles
|
|||
|
|
}
|