|
|
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,
|
|
|
max: 100
|
|
|
});
|
|
|
app.use('/api', limiter);
|
|
|
|
|
|
app.use(express.json());
|
|
|
app.use(express.static('public'));
|
|
|
|
|
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
|
|
|
|
|
|
|
|
|
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);
|
|
|
}); |