Node.js 安全实践与生产部署

Node.js 生产级安全与部署:输入校验、Helmet 安全头部、CORS 配置、Rate Limiting、JWT 安全、PM2 进程管理、Docker 容器化与 CI/CD 流水线。

1. Express 安全中间件

const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const hpp = require('hpp');
const mongoSanitize = require('express-mongo-sanitize');

const app = express();

// 安全头部
app.use(helmet({
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            scriptSrc: ["'self'", "'unsafe-inline'"],
            styleSrc: ["'self'", "'unsafe-inline'"]
        }
    },
    hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }
}));

// CORS
app.use(cors({
    origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
    allowedHeaders: ['Content-Type', 'Authorization']
}));

// 全局限流
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000,  // 15 分钟
    max: 100,                   // 每 IP 100 请求
    standardHeaders: true,
    legacyHeaders: false,
    handler: (req, res) => res.status(429).json({ error: 'Too many requests' })
});
app.use('/api/', limiter);

// 严格限流(登录/注册)
const authLimiter = rateLimit({
    windowMs: 60 * 60 * 1000,
    max: 5,
    skipSuccessfulRequests: true
});
app.use('/api/auth/login', authLimiter);

// 参数污染防护
app.use(hpp());

// NoSQL 注入防护
app.use(mongoSanitize());

// 输入大小限制
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ extended: true, limit: '10kb' }));

2. JWT 安全实践

const jwt = require('jsonwebtoken');

// 签发(短有效期)
const accessToken = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m', issuer: 'myapp', audience: 'myapp-client' }
);

const refreshToken = jwt.sign(
    { userId: user.id, type: 'refresh' },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
);

// 验证中间件
function authenticate(req, res, next) {
    const auth = req.headers.authorization;
    if (!auth?.startsWith('Bearer ')) {
        return res.status(401).json({ error: 'Missing token' });
    }
    
    try {
        const token = auth.substring(7);
        req.user = jwt.verify(token, process.env.JWT_SECRET, {
            issuer: 'myapp',
            audience: 'myapp-client',
            clockTolerance: 30  // 30 秒时钟偏差容忍
        });
        next();
    } catch (err) {
        res.status(401).json({ error: 'Invalid token' });
    }
}

3. PM2 进程管理

// ecosystem.config.js
module.exports = {
    apps: [{
        name: 'api-server',
        script: './dist/main.js',
        instances: 'max',           // 使用全部 CPU
        exec_mode: 'cluster',       // 集群模式
        max_memory_restart: '1G',   // 内存超限重启
        env: { NODE_ENV: 'production' },
        log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
        error_file: './logs/err.log',
        out_file: './logs/out.log',
        merge_logs: true,
        autorestart: true,
        kill_timeout: 5000,
        listen_timeout: 10000,
        // 优雅关闭
        wait_ready: true,
        shutdown_with_message: true
    }]
};
# 部署命令
pm2 start ecosystem.config.js
pm2 reload api-server          # 零停机重载
pm2 scale api-server +2        # 扩容
pm2 monit                      # 监控

4. 生产检查清单

□ 依赖安全:npm audit fix
□ 环境变量:dotenv / 密钥管理系统
□ HTTPS:TLS 1.2+、HSTS
□ 日志:结构化日志(Winston/Pino),不记录敏感信息
□ 监控:PM2 + APM(New Relic / Datadog)
□ 健康检查:/health 端点
□ 优雅关闭:SIGTERM/SIGINT 处理
□ 备份策略:数据库定时备份
□ 灰度发布:蓝绿部署或金丝雀

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「nodejs」更多文章

  1. Node.js ORM 深度对比:Prisma、TypeORM、Sequelize 与 Drizzle
  2. Node.js 设计模式与最佳实践:从 SOLID 到六边形架构
  3. Node.js 高级测试策略:从单元测试到混沌工程的完整实践