File size: 1,660 Bytes
4c025e9
 
 
006ee19
4c025e9
 
 
 
 
 
 
 
 
 
006ee19
4c025e9
 
 
006ee19
4c025e9
 
 
 
 
006ee19
4c025e9
 
 
 
 
 
006ee19
4c025e9
 
 
006ee19
 
4c025e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const jwt = require('jsonwebtoken');
const asyncHandler = require('express-async-handler');
const User = require('../models/User');
const logger = require('../utils/logger');

// 保护路由 - 验证 JWT Token
const protect = asyncHandler(async (req, res, next) => {
  let token;

  // 从 Authorization 头获取 token
  if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
    try {
      // 获取 token
      token = req.headers.authorization.split(' ')[1];
      logger.info(`验证令牌: ${token.substring(0, 15)}...`);

      // 验证 token
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      logger.info(`令牌有效,用户ID: ${decoded.id}`);

      // 获取用户并添加到请求对象中,不包含密码
      req.user = await User.findById(decoded.id).select('-password');

      if (!req.user) {
        logger.warn(`令牌有效但用户不存在: ${decoded.id}`);
        res.status(401);
        throw new Error('未授权,用户不存在');
      }

      next();
    } catch (error) {
      logger.error(`令牌验证失败: ${error.message}`);
      res.status(401);
      throw new Error('未授权,token 无效');
    }
  } else {
    logger.warn(`未提供认证令牌: ${req.originalUrl}`);
    res.status(401);
    throw new Error('未授权,未提供 token');
  }
});

// 限制仅管理员访问
const admin = (req, res, next) => {
  if (req.user && req.user.isAdmin) {
    next();
  } else {
    res.status(403);
    throw new Error('未授权,仅管理员可访问');
  }
};

module.exports = { protect, admin };