File size: 2,630 Bytes
3b4170f
158961a
10c367b
158961a
 
10c367b
158961a
 
 
3b4170f
158961a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10c367b
 
158961a
 
3b4170f
 
565dfa2
 
158961a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3b4170f
158961a
 
 
 
3b4170f
 
10c367b
 
 
 
 
5788bb9
 
 
10c367b
 
5788bb9
 
10c367b
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
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);
    });