求教 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)
求大神帮忙看看, 谢谢了~
根据你提供的代码和描述,问题可能出在CSRF(跨站请求伪造)中间件的配置上。在Express 3.x版本中,express.csrf()
用于生成和验证CSRF令牌。你的问题可能是由于CSRF令牌没有正确地传递到后端。
解决方案
-
确保表单中包含CSRF令牌: 在表单中添加一个隐藏字段来传递CSRF令牌。你已经在Jade模板中做了这一点,但需要确保这个字段的值始终是最新的。
-
更新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
关键点解释
-
CSRF中间件:
csrf({ cookie: true })
:这会从Cookie中读取CSRF令牌。res.locals.token = req.csrfToken()
:这会在每次请求时生成一个新的CSRF令牌,并将其添加到视图的本地变量中。
-
表单:
<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
关键点解释
- CSRF中间件:使用
csurf
中间件进行CSRF保护。 - CSRF Token注入:在表单中添加隐藏的
_csrf
字段,该字段的值通过req.csrfToken()
获取。 - 路由保护:确保POST请求路由使用了CSRF保护中间件。
以上步骤应该可以解决你遇到的CSRF错误问题。如果仍然出现问题,请检查是否有其他中间件或设置影响了CSRF token的传递。