Spaces:
Paused
Paused
File size: 3,387 Bytes
146bdba |
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
import { createLogger } from '../utils/logger.js';
import { config } from '../config/index.js';
const logger = createLogger('AuthMiddleware');
// 存储有效的会话令牌(实际生产环境中应使用Redis或其他持久化存储)
const sessionTokens = new Map();
/**
* 认证中间件
* 验证请求的Bearer token
*/
export function authenticate(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
logger.warning(`认证失败: 缺少Bearer token - IP: ${req.ip}`);
return res.status(401).json({
error: {
message: "Authentication required. Please provide a valid Bearer token.",
type: "authentication_error"
}
});
}
const token = authHeader.split(' ')[1];
// 首先检查是否是管理员会话令牌
if (sessionTokens.has(token)) {
const session = sessionTokens.get(token);
// 检查会话是否过期(24小时)
if (new Date().getTime() - session.timestamp < 24 * 60 * 60 * 1000) {
logger.debug(`认证成功(管理员会话) - IP: ${req.ip}`);
req.user = session.user;
return next();
} else {
// 会话过期,删除令牌
sessionTokens.delete(token);
}
}
// 检查是否是API令牌
if (token !== config.server.authToken) {
logger.warning(`认证失败: 无效的token - IP: ${req.ip}`);
return res.status(401).json({
error: {
message: "Invalid authentication credentials",
type: "authentication_error"
}
});
}
logger.debug(`认证成功(API令牌) - IP: ${req.ip}`);
next();
}
/**
* 添加会话令牌
*/
export function addSessionToken(token, user) {
sessionTokens.set(token, {
user,
timestamp: new Date().getTime()
});
}
/**
* 清理过期的会话令牌
*/
setInterval(() => {
const now = new Date().getTime();
for (const [token, session] of sessionTokens.entries()) {
if (now - session.timestamp > 24 * 60 * 60 * 1000) {
sessionTokens.delete(token);
}
}
}, 60 * 60 * 1000); // 每小时清理一次
/**
* 请求日志中间件
* 记录所有请求的详细信息
*/
export function requestLogger(req, res, next) {
const start = Date.now();
// 保存原始的 end 方法
const originalEnd = res.end;
// 重写 end 方法以记录请求完成时间
res.end = function(...args) {
const duration = Date.now() - start;
logger.request(req.method, req.path, res.statusCode, duration);
return originalEnd.apply(this, args);
};
next();
}
/**
* 错误处理中间件
* 统一处理所有未捕获的错误
*/
export function errorHandler(err, req, res, next) {
logger.error(`未处理的错误: ${err.message}`, err);
// 如果响应已经发送,则交给默认错误处理器
if (res.headersSent) {
return next(err);
}
// 发送错误响应
res.status(500).json({
error: {
message: process.env.NODE_ENV === 'production'
? 'Internal server error'
: err.message,
type: 'server_error'
}
});
}
/**
* 请求体大小限制中间件配置
*/
export const requestLimits = {
json: { limit: '50mb' },
urlencoded: { extended: true, limit: '50mb' }
};
|