const express = require('express'); const winston = require('winston'); const fs = require('fs').promises; const path = require('path'); const rateLimit = require('express-rate-limit'); const { promises: fsPromises } = require('fs'); const helmet = require('helmet'); const jwt = require('jsonwebtoken'); const app = express(); const port = process.env.PORT || 7860; // 配置日志记录器 const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }) ] }); if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple() })); } // 安全中间件 app.use(helmet()); // 速率限制 const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100 // 每个IP限制100个请求 }); app.use('/api', limiter); app.use(express.json()); app.use(express.static('public')); // JWT 密钥 const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key'; // 中间件:验证 JWT const authenticateJWT = (req, res, next) => { const authHeader = req.headers.authorization; if (authHeader) { const token = authHeader.split(' ')[1]; jwt.verify(token, JWT_SECRET, (err, user) => { if (err) { return res.sendStatus(403); } req.user = user; next(); }); } else { res.sendStatus(401); } }; // 路由 const authRoutes = require('./routes/auth'); const commandRoutes = require('./routes/command'); app.use('/api', authRoutes); app.use('/api', authenticateJWT, commandRoutes); // 错误处理中间件 app.use((err, req, res, next) => { logger.error(`未捕获的错误: ${err.message}`); res.status(500).json({ error: '服务器内部错误' }); }); // 确保命令历史文件存在 const historyFilePath = path.join(__dirname, 'data', 'command_history.json'); fsPromises.access(historyFilePath) .catch(() => fsPromises.writeFile(historyFilePath, '[]')) .then(() => { app.listen(port, () => { logger.info(`Web 命令执行应用正在监听 http://localhost:${port}`); }); }) .catch(err => { logger.error('无法创建命令历史文件:', err); process.exit(1); });