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

Node.js表单CSRF令牌验证失败:POST请求返回403错误求助

解决CSRF令牌验证失败(403 Forbidden)的问题

看起来你遇到的核心问题是全局挂载的CSRF中间件在文件上传中间件(推测是Multer)之前执行,导致multipart/form-data类型的请求在CSRF验证时,请求体还没被解析,CSRF中间件无法从req.body中获取_csrf令牌,从而触发验证失败。下面是具体的排查和修复步骤:

1. 核心问题分析

你的表单使用了multipart/form-data格式,而body-parser.urlencoded不会解析这种类型的请求体。你全局挂载了csurf中间件,它会在所有请求到达路由处理函数前执行验证,但此时文件上传中间件还没解析请求内容,req.body是空的,自然找不到_csrf字段,最终抛出invalid csrf token错误。

2. 具体修复步骤

步骤一:调整CSRF中间件的使用方式(从全局改为路由级)

在app.js中移除全局的CSRF中间件挂载,改为在需要保护的路由中按需使用:

// app.js 中注释掉这一行全局CSRF挂载
// app.use(csrf());

然后在fileRoutes.js中引入并创建CSRF保护中间件,配合文件上传中间件调整执行顺序:

// 在fileRoutes.js顶部添加依赖引入与配置
var csrf = require('csurf');
var multer = require('multer');
// 基于session存储CSRF令牌(和你当前的session配置匹配)
var csrfProtection = csrf({ cookie: false });
// 配置multer(根据你的需求调整文件存储路径)
var upload = multer({ dest: './uploads/' });

// 修改GET路由:添加csrfProtection生成令牌,并传递给模板
router.get('/', csrfProtection, function(req,res){
  File.find(function(err, files){
    res.render('views/layout',{files:files, _csrf: req.csrfToken()});
  });
});

// 修改POST路由:先让multer解析Multipart请求,再执行CSRF验证
router.post('/addfile', upload, csrfProtection, function(req,res){
  if (req.fileValidationError) {
    return res.end("Error PDF");
  } else {
    for (var i = 0; i < req.files.length; i++) {
      var files = new File ();
      files.fieldname= req.files[i].fieldname;
      files.originalname= req.files[i].originalname;
      files.encoding= req.files[i].encoding; // 修复拼写错误:encodin -> encoding
      files.path= req.files[i].path;
      files.save(function(err, data){
        // 可选:添加错误日志,方便排查保存失败问题
        if(err) console.error('文件数据保存失败:', err);
      });
    }
    res.redirect('/');
  }
});

步骤二:确保Multer配置正确

Multer默认会解析multipart/form-data中的文本字段(包括你的_csrf隐藏字段),只要你的upload配置没有禁用该功能,req.body._csrf就会被正确解析,供CSRF中间件验证使用。

步骤三:修复代码中的拼写错误

你在fileRoutes.js中存在一个小错误:req.files[i].encodin应改为req.files[i].encoding,否则保存到数据库的encoding字段会是undefined。

3. 额外优化建议

  • 调整app.js的视图路径配置:app.set('views',path.join(__dirname, 'views'));,这样渲染模板时可以直接写res.render('layout'),更符合Express的规范。
  • 优化Session配置:将saveUninitialized: true改为false,避免创建不必要的空Session,提升应用性能。

内容的提问来源于stack exchange,提问作者Valentin Valentyn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:04:41