求教 Nodejs express 3.2 csrf , form提交以后总是报错.

求教 Nodejs express 3.2 csrf , form提交以后总是报错.

app.configure(function () {
var viewsRoot = path.join(__dirname, ‘views’);
app.set(‘view engine’, ‘jade’);
app.set(‘views’, viewsRoot);
app.use(express.cookieParser());
app.use(express.session({
secret: config.session_secret
}));

app.use(express.csrf());

app.use(function(req, res, next){ res.locals.token = req.session._csrf; next(); }); });

上面是 app.js里的代码, 用的jade框架,form页面能显示出来.

<input type="hidden" name="_csrf" value="4UfvarvZ7xXx_Ylt-1VNhFtX">

但是一提交到另外一个页面:

exports.makenew = function(req,res,next ) {
  console.log("here u r. what r u look for?");
  console.log(req.body);
}

第一console都不会显示 直接报错:

Express
403 Error: Forbidden
at Object.exports.error (/mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/utils.js:60:13)
at Object.handle (/mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/middleware/csrf.js:54:41)
at next (/mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at next (/mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/middleware/session.js:313:9)
at /mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/middleware/session.js:337:9
at /mydata/myweb/nodejs/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:50:9
at process._tickCallback (node.js:415:13)

求大神帮忙看看, 谢谢了~


5 回复

根据你提供的代码和描述,问题可能出在CSRF(跨站请求伪造)中间件的配置上。在Express 3.x版本中,express.csrf()用于生成和验证CSRF令牌。你的问题可能是由于CSRF令牌没有正确地传递到后端。

解决方案

  1. 确保表单中包含CSRF令牌: 在表单中添加一个隐藏字段来传递CSRF令牌。你已经在Jade模板中做了这一点,但需要确保这个字段的值始终是最新的。

  2. 更新CSRF中间件的使用方式: 确保在处理请求之前正确设置了CSRF令牌,并且在表单提交时正确地包含了该令牌。

示例代码

app.js

var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var csrf = require('csurf');

var app = express();

app.configure(function () {
  var viewsRoot = path.join(__dirname, 'views');
  app.set('view engine', 'jade');
  app.set('views', viewsRoot);

  app.use(cookieParser());
  app.use(session({
    secret: config.session_secret
  }));

  // 创建CSRF保护中间件
  var csrfProtection = csrf({ cookie: true });

  // 使用CSRF保护中间件
  app.use(csrfProtection);

  // 将CSRF令牌暴露给视图
  app.use(function(req, res, next) {
    res.locals.token = req.csrfToken();
    next();
  });
});

// 定义路由
app.get('/form', function(req, res) {
  res.render('form');
});

app.post('/submit', function(req, res) {
  console.log("Here you are. What are you looking for?");
  console.log(req.body);
  res.send('Form submitted successfully!');
});

module.exports = app;

Jade模板 (form.jade)

doctype html
html
  head
    title CSRF Form
  body
    form(action='/submit', method='POST')
      input(type='hidden', name='_csrf', value=token)
      label(for='name') Name:
      input(type='text', id='name', name='name')
      button(type='submit') Submit

关键点解释

  1. CSRF中间件

    • csrf({ cookie: true }):这会从Cookie中读取CSRF令牌。
    • res.locals.token = req.csrfToken():这会在每次请求时生成一个新的CSRF令牌,并将其添加到视图的本地变量中。
  2. 表单

    • <input type='hidden' name='_csrf' value=token>:确保表单中包含CSRF令牌。

通过这种方式,你可以确保CSRF令牌正确地生成并在表单提交时被验证。这样可以避免403错误。


csrf原理是比较session._csrf是否等于提交参数的_csrf,具体到楼主的问题,就是session._csrf是否等于req.body._csrf。既然抛出403,两者肯定不相等。根据代码session._csrf没问题,那么很可能就是req.body._csrf出问题了,但是form的_csrf有值,进一步推测req.body为空。req.body为空!?回头一看代码,csrf中间件前面没有bodyParser中间呢。。。。以上。

so嘎 thank you so much. 果然是呢,刚刚改了 太感谢了!!!

神逻辑!

从你的描述来看,问题出在CSRF(跨站请求伪造)保护上。Express使用csurf中间件来处理CSRF保护,默认情况下会检查每个POST、PUT、DELETE等方法的请求是否包含有效的CSRF token。

首先,确保你已经安装了csurf中间件:

npm install csurf --save

接下来,在你的app.js文件中正确配置CSRF中间件,并确保在表单中正确地插入了CSRF token。

修改后的app.js配置

var express = require('express'),
    cookieParser = require('cookie-parser'),
    session = require('express-session'),
    csurf = require('csurf');

var app = express();

app.set('view engine', 'jade');
app.set('views', path.join(__dirname, 'views'));

app.use(cookieParser());
app.use(session({
  secret: config.session_secret
}));

// 创建并使用CSRF保护中间件
var csrfProtection = csurf({ cookie: true });
app.use(csrfProtection);

// 在响应中暴露CSRF token
app.use(function(req, res, next) {
  res.locals.token = req.csrfToken();
  next();
});

app.get('/form', function(req, res) {
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/submit', csrfProtection, function(req, res) {
  console.log("here u r. what r u look for?");
  console.log(req.body);
  res.send('Form submitted successfully!');
});

app.listen(3000);

修改后的表单页面

在Jade模板中,确保正确插入CSRF token:

form(action='/submit' method='post')
  input(type='hidden' name='_csrf' value='#{csrfToken}')
  // 其他表单字段
  button(type='submit') Submit

关键点解释

  1. CSRF中间件:使用csurf中间件进行CSRF保护。
  2. CSRF Token注入:在表单中添加隐藏的_csrf字段,该字段的值通过req.csrfToken()获取。
  3. 路由保护:确保POST请求路由使用了CSRF保护中间件。

以上步骤应该可以解决你遇到的CSRF错误问题。如果仍然出现问题,请检查是否有其他中间件或设置影响了CSRF token的传递。

回到顶部