文章目录

Node.js 安全:XSS、CSRF 防护

发布于 2026-04-06 23:52:18 · 浏览 13 次 · 评论 0 条

Node.js 安全:XSS、CSRF 防护

直接配置 Node.js 应用拦截恶意脚本与伪造请求。按顺序执行以下步骤即可完成基础防护部署。


阶段一:阻断 XSS(跨站脚本)注入

  1. 运行 终端命令 npm install express helmet escape-html 安装 核心安全依赖库。
  2. 新建 入口文件 app.js引入 模块并 初始化 Express 应用实例。
  3. 挂载 helmet 中间件,启用 默认 HTTP 安全响应头拦截规则。
    
    const express = require('express');
    const helmet = require('helmet');
    const { escape } = require('escape-html');
    const app = express();

// 注入默认安全头集合
app.use(helmet());

4. **覆盖** 默认内容安全策略。将下方配置追加至中间件链,**限制** 浏览器仅加载同源静态资源。
```javascript
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'"],
      imgSrc: ["'self'", "data:"],
      connectSrc: ["'self'"]
    }
  })
);
  1. 替换 动态数据渲染逻辑。在输出任何用户提交或数据库查询的字段前,调用 escape 函数转换特殊字符为 HTML 实体。
    app.get('/profile', (req, res) => {
    const safeName = escape(req.query.username);
    res.send(`欢迎回来,${safeName}`);
    });
  2. 发送 测试请求验证拦截效果。在终端执行 curl -I http://localhost:3000/profile核对 响应头是否包含 content-security-policy 字段且值未被覆盖为默认放行状态。

阶段二:拦截 CSRF(跨站请求伪造)

  1. 安装 会话与加密依赖 npm install express-session crypto
  2. 创建 会话配置对象,设置 Cookie 的安全传输与生命周期参数。
    
    const session = require('express-session');

app.use(session({
secret: process.env.SESSION_SECRET || 'strong-random-key-here',
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 86400000
}
}));

3. **配置** 关键 Cookie 安全参数。严格对照下表调整会话行为,阻断第三方站点劫持请求。

| 参数名称 | 推荐配置值 | 防护作用 |
| :--- | :--- | :--- |
| `secure` | `true` | 强制仅通过 HTTPS 协议传输,拦截中间人劫持 |
| `httpOnly` | `true` | 禁止前端 JavaScript 读取,阻断 XSS 窃取会话 |
| `sameSite` | `'strict'` | 拦截跨站请求携带,彻底屏蔽第三方站点伪造调用 |

4. **编写** CSRF 令牌生成器。在路由处理前 **生成** 32 字节随机十六进制串,**存入** 当前会话与作用域。
```javascript
const crypto = require('crypto');

function generateCSRFToken(req, res, next) {
  if (!req.session.csrfToken) {
    req.session.csrfToken = crypto.randomBytes(32).toString('hex');
  }
  res.locals.csrfToken = req.session.csrfToken;
  next();
}

app.use(generateCSRFToken);
  1. 注入 隐藏字段至所有可提交表单。在 EJS 或 HTML 模板中添加以下代码,确保 每次页面刷新获取新令牌。
    <form action="/transfer" method="POST">
    <input type="hidden" name="_csrf" value="<%= csrfToken %>">
    <input type="number" name="amount" placeholder="转账金额" required>
    <button type="submit">确认转账</button>
    </form>
  2. 开发 令牌校验中间件。使用恒定时间比较算法 验证 请求体携带的 _csrf 与会话存储值是否完全匹配,失败则立即终止处理。
    
    function verifyCSRFToken(req, res, next) {
    const requestToken = req.body._csrf;
    const sessionToken = req.session.csrfToken;

if (!requestToken || typeof sessionToken !== 'string' || typeof requestToken !== 'string') {
return res.status(403).json({ error: 'Missing CSRF token' });
}

const reqBuf = Buffer.from(requestToken, 'hex');
const sessBuf = Buffer.from(sessionToken, 'hex');

if (reqBuf.length !== 32 || sessBuf.length !== 32 || !crypto.timingSafeEqual(reqBuf, sessBuf)) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
next();
}

7. **绑定** 校验逻辑至变更类路由。将 `verifyCSRFToken` **放置** 在解析表单中间件之后,目标路由之前。
```javascript
app.use(express.urlencoded({ extended: true }));
app.post('/transfer', verifyCSRFToken, (req, res) => {
  res.json({ status: 'success', amount: req.body.amount });
});

阶段三:验证请求链路安全

  1. 构造 跨站脚本测试载荷。新建 test-xss.html写入 <script>alert('vulnerable')</script> 并作为 URL 查询参数提交至受保护路由。
  2. 观察 浏览器控制台与页面渲染结果。确认控制台未执行任何 alert 弹窗,页面仅输出转义后的纯文本节点。
  3. 核对 伪造请求拦截流程。对照下方时序结构确认各节点拦截逻辑是否生效。
    graph TD A["浏览器发起 GET 请求"] --> B["服务端返回包含令牌的表单"] B --> C["用户填写并提交 POST 请求"] C --> D{"校验 _csrf 令牌"} D -- "匹配成功" --> E["执行数据写入 返回 200"] D -- "匹配失败" --> F["拒绝请求 返回 403"] G["恶意站点加载伪造页面"] -.->|自动携带 Session Cookie| C C -.->|缺少 _csrf 字段| D
  4. 执行 依赖漏洞扫描。在终端运行 npm audit查看 已知安全漏洞清单,并 执行 npm audit fix 更新受影响的子依赖。
  5. 配置 自动化安全巡检脚本。将 npm audit 加入 CI/CD 流水线,设定 exit code 非零时自动阻断部署任务。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文