You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExpressJS:拆分路由后CSRF配置错误排查——无法生成CSRF令牌

问题分析与修复方案

你遇到的问题核心是在路由文件里错误创建了新的Express实例,且中间件挂载到了这个无关实例上,导致CSRF模块依赖的Cookie解析逻辑没有加入主应用的请求处理链中,最终令牌生成/验证失效。下面具体拆解问题和修复步骤:

核心错误点

  1. 重复创建Express实例:在routes-api.js中你声明了const app = express();,但这个新实例和index.js里的主应用完全独立,你在这个新app上挂载的cookieParser()根本不会作用到主应用的请求上,而CSRF模块依赖Cookie解析来生成和校验令牌,自然无法正常工作。
  2. 中间件挂载位置错误:你把cookieParser()挂载到了新的app实例上,而非当前路由的中间件链或主应用的全局中间件链中,导致CSRF无法获取到必要的Cookie上下文。

修复后的代码

第一步:修正routes-api.js

删除多余的Express实例,将中间件挂载到当前路由上,同时去掉重复的bodyParser引入(主应用已全局配置):

var cookieParser = require('cookie-parser');
var csrf = require('csurf');
var express = require('express');
const path = require("path");
const router = express.Router();

// 配置路由级中间件
var csrfProtection = csrf({ cookie: true });
// 将cookieParser挂载到当前router,确保在csrfProtection之前执行
router.use(cookieParser());

router.get("/", csrfProtection, (req, res) => {
  console.log("csrf: " + req.csrfToken());
  // 注意:sendFile不支持模板变量传递,需替换为模板渲染或手动替换内容
  const fs = require('fs');
  const filePath = path.join(__dirname + '/send.html');
  fs.readFile(filePath, 'utf8', (err, content) => {
    if (err) return res.status(500).send('加载HTML文件失败');
    // 假设send.html中有占位符<input type="hidden" name="_csrf" value="{{csrfToken}}">
    const updatedContent = content.replace('{{csrfToken}}', req.csrfToken());
    res.send(updatedContent);
  });
});

module.exports = router;

第二步:优化index.js(可选但更规范)

将cookieParser移到主应用的全局中间件链中,让所有路由共享该中间件,避免在路由文件中重复配置:

//Creación de un servidor con express
const express = require("express");
const app = express(); //Inicializamos express
//Accedemos a otros módulos
const morgan = require("morgan");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
const cookieParser = require('cookie-parser'); // 新增引入cookieParser
//Accedemos a propiedades de configuración
const config = require("./config");
//Rutas
const routes = require("./routes");
const routesAPI = require("./routes-api");

//Settings
app.set("app-name", config.server);
app.set("port", config.port);
app.set("super-secret", config.secret);

//Middlewares
// use body parser so we can get info from POST and/or URL parameters
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(morgan("dev")); //Log request to the console
app.use(cookieParser()); // 全局配置Cookie解析中间件
app.use((req, res, next) => {
  console.log("Pasamos por la segunda función!!!");
  next();
});

//Routing
app.use("/api", routesAPI);
app.use(routes);

//Server
app.listen(app.get("port"), () => {
  console.log("Servidor " + app.get("app-name") + " escuchando!!!");
});

如果做了这一步,routes-api.js里的router.use(cookieParser())就可以删除了。

额外说明

你原本用res.sendFile传递csrfToken参数是无效的,因为sendFile仅用于发送静态文件,不支持模板变量替换。上面的修复代码中用了手动读取文件并替换占位符的方式,你也可以改用EJS、Pug等模板引擎,通过res.render来渲染页面并传入令牌。

内容的提问来源于stack exchange,提问作者José Carlos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:07:57