feat: 实现统一日志系统和维护模式功能

This commit is contained in:
zhang1106
2026-04-28 10:57:17 +08:00
parent 763e425f78
commit bf2cd221b9
43 changed files with 1966 additions and 430 deletions
+8 -14
View File
@@ -1,5 +1,6 @@
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const logger = require('../utils/logger').module('AuthMiddleware');
function getJwtSecret() {
const envSecret = process.env.JWT_SECRET;
@@ -124,11 +125,10 @@ const authMiddleware = async (req, res, next) => {
user = await User.findByPk(decoded.userId);
} catch (dbError) {
// 数据库查询错误
console.error('[认证中间件] 数据库查询失败:', {
logger.error('数据库查询失败', {
userId: decoded.userId,
error: dbError.message,
stack: dbError.stack,
timestamp: new Date().toISOString(),
});
return res.status(500).json({
success: false,
@@ -137,10 +137,9 @@ const authMiddleware = async (req, res, next) => {
}
if (!user) {
console.warn('[认证中间件] 用户不存在:', {
logger.warn('用户不存在', {
userId: decoded.userId,
username: decoded.username,
timestamp: new Date().toISOString(),
});
return res.status(401).json({
success: false,
@@ -149,10 +148,9 @@ const authMiddleware = async (req, res, next) => {
}
if (user.status === 'locked') {
console.warn('[认证中间件] 账户已被锁定:', {
logger.warn('账户已被锁定', {
userId: user.userId,
username: user.username,
timestamp: new Date().toISOString(),
});
return res.status(403).json({
success: false,
@@ -161,10 +159,9 @@ const authMiddleware = async (req, res, next) => {
}
if (user.status === 'inactive') {
console.warn('[认证中间件] 账户已禁用:', {
logger.warn('账户已禁用', {
userId: user.userId,
username: user.username,
timestamp: new Date().toISOString(),
});
return res.status(403).json({
success: false,
@@ -177,13 +174,12 @@ const authMiddleware = async (req, res, next) => {
next();
} catch (error) {
// 捕获未预期的错误
console.error('[认证中间件] 未预期的错误:', {
logger.error('未预期的错误', {
error: error.message,
stack: error.stack,
url: req?.url,
method: req?.method,
ip: req?.ip,
timestamp: new Date().toISOString(),
});
return res.status(500).json({
success: false,
@@ -206,10 +202,9 @@ const optionalAuth = async (req, res, next) => {
user = await User.findByPk(decoded.userId);
} catch (dbError) {
// 数据库错误时不中断请求,仅记录日志
console.warn('[可选认证] 数据库查询失败:', {
logger.warn('可选认证数据库查询失败', {
userId: decoded.userId,
error: dbError.message,
timestamp: new Date().toISOString(),
});
// 继续执行,不设置用户信息
next();
@@ -226,10 +221,9 @@ const optionalAuth = async (req, res, next) => {
next();
} catch (error) {
// 可选认证失败不影响主流程,仅记录日志
console.warn('[可选认证] 认证失败(已忽略):', {
logger.warn('可选认证失败(已忽略)', {
error: error.message,
url: req?.url,
timestamp: new Date().toISOString(),
});
next();
}
+31
View File
@@ -0,0 +1,31 @@
const { isMaintenanceModeActive, MaintenanceMode } = require('../utils/maintenanceMode');
/**
* 维护模式中间件
* 维护期间拦截所有非白名单请求,返回 503 状态码
*/
function maintenanceMiddleware(req, res, next) {
if (!isMaintenanceModeActive()) {
return next();
}
const isAllowed = MaintenanceMode.allowedRoutes.some((route) =>
req.path.startsWith(route)
);
if (isAllowed) {
return next();
}
return res.status(503).json({
success: false,
message: '系统正在维护中,请稍后再试',
maintenance: {
active: true,
reason: MaintenanceMode.reason,
startTime: MaintenanceMode.startTime,
},
});
}
module.exports = { maintenanceMiddleware };
+40
View File
@@ -0,0 +1,40 @@
/**
* HTTP 请求日志中间件
* 为每个请求生成唯一 ID,记录请求/响应信息
*/
const logger = require('../utils/logger');
const crypto = require('crypto');
/**
* 请求日志中间件
* 记录每个 HTTP 请求的方法、URL、状态码、耗时、用户ID 等信息
*/
const requestLogger = (req, res, next) => {
const requestId = crypto.randomBytes(4).toString('hex');
const startTime = Date.now();
req.requestId = requestId;
res.on('finish', () => {
const duration = Date.now() - startTime;
const level = res.statusCode >= 500 ? 'error'
: res.statusCode >= 400 ? 'warn' : 'debug';
logger[level](`${req.method} ${req.originalUrl}`, {
module: 'HTTP',
requestId,
method: req.method,
url: req.originalUrl,
statusCode: res.statusCode,
duration: `${duration}ms`,
ip: req.ip || req.connection.remoteAddress,
userAgent: req.get('User-Agent'),
userId: req.user?.userId || null,
});
});
next();
};
module.exports = requestLogger;
+3 -1
View File
@@ -1,3 +1,5 @@
const logger = require('../utils/logger').module('ValidationMiddleware');
const validate = (schema, source = 'body') => {
return async (req, res, next) => {
const data = source === 'query' ? req.query : req.body;
@@ -73,7 +75,7 @@ const validate = (schema, source = 'body') => {
});
}
console.error('验证中间件错误:', error);
logger.error('验证中间件错误', { error: error.message, stack: error.stack });
return res.status(500).json({
error: '验证过程发生错误',
message: error.message,