Node Express和csurf – 403(Forbidden)无效的csrf标记

通过浏览,并尝试了一切,我可以find在这里,谷歌search其他地方…我只是无法克服这一点。 我正在使用Node,Express,EJS,并试图在窗体上使用csurf,这是张贴w / jQuery的Ajax。 无论我如何configurationcsurf,我都会得到“403(Forbidden)无效的csrf标记”

我已经尝试在app.js和控制器中全局configuration。 这是我在app.js中尝试的:

var express = require('express'); var session = require('express-session'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var mysql = require('mysql'); var flash = require("connect-flash"); var csrf = require("csurf"); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(logger('dev')); app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: false})); app.use(session({ secret: 'somethingsecret', resave: true, saveUninitialized: true, httpOnly: true, secure: false })); app.use(csrf()); app.use(function (req, res, next) { var token = req.csrfToken(); res.cookie('XSRF-TOKEN', token); res.locals.csrfToken = token; console.log("csrf token = " + token); next(); }); app.use(flash()); app.use(express.static(path.join(__dirname, 'public'))); app.use(function (err, req, res, next) { if (err.code !== 'EBADCSRFTOKEN') return next(err); // handle CSRF token errors here res.status(403); res.send('form tampered with'); }) //routing var routes = require('./routes/index'); var users = require('./routes/users'); var register = require('./routes/register'); app.use('/', routes); app.use('/users', users); app.use('/register', register); 

用这个控制器:

 var express = require("express"); var router = express.Router(); var bodyParser = require("body-parser"); var userSvc = require("../service/userservice"); var jsonParser = bodyParser.json(); router.get("/", function(req, res, next) { console.log("token = " + token); userSvc.getAllPublicRoles(function(data) { res.render("register", { title: "Register a new account", roles: data }); }); }); router.post("/new", jsonParser, function(req, res, next) { userSvc.addUser(req.body, function(result) { console.log("New user id = " + result.insertId); res.send('{"success" : "Updated Successfully", "status" : 200}'); }); }); 

…这个观点:

形成:

 <form id="registerForm" class="form-horizontal" method="post"> <input type="hidden" name="_csrf" value="<%= csrfToken %>" /> 

ajax电话:

  $.ajax({ url: "/register/new", type: "POST", dataType: "json", data: user }).done(function(data) { if (data) { console.log("Success! = " + data); } }).fail(function(data) { console.log("Something went wrong: " + data.responseText); }); 

然后,我只是试着在控制器中做所有事情,从app.js中删除所有引用,调用等,并使用与上面相同的form和ajax调用:

 var express = require("express"); var router = express.Router(); var bodyParser = require("body-parser"); var csrf = require("csurf"); var userSvc = require("../service/userservice"); var csrfProtection = csrf(); var jsonParser = bodyParser.json(); router.get("/", csrfProtection, function(req, res, next) { var token = req.csrfToken(); console.log("token = " + token); userSvc.getAllPublicRoles(function(data) { res.render("register", { title: "Register a new account", csrfToken: token, roles: data }); }); }); router.post("/new", jsonParser, csrfProtection, function(req, res, next) { userSvc.addUser(req.body, function(result) { console.log("New user id = " + result.insertId); res.send('{"success" : "Updated Successfully", "status" : 200}'); }); }); 

不知道从哪里去。 我在业余时间用了两个星期左右,所以请原谅我的无知。

如果您想将令牌存储在cookie而不是会话中,请让csurf为您创buildcookie,例如

 // Store the token in a cookie called '_csrf' app.use(csrf({cookie: true)); // Make the token available to all views app.use(function (req, res, next){ res.locals._csrf = req.csrfToken(); next(); }); 

然后,当您使用AJAX进行调用时,您需要确保该令牌可用,或者通过POST的数据,或者作为自定义请求头(如“xsrf-token”)。

在那一刻,你提供的令牌表单,但不是实际的请求(使用AJAX发送)。

例如,您可以在AJAX设置中渲染令牌:

 $.ajaxSetup({ headers: {"X-CSRF-Token": "{{csrfToken}}" } }); 

经过几个小时的故障排除和search,我find了一个帮助解答的post。 我所需要的只是传递ajax文章中的标题值。 有道理,我只是忽略了它。 像这样:

 <input type="hidden" id="_csrf" name="_csrf" value="<%= csrfToken %>" /> 

…然后在jQuery中:

  $.ajaxSetup({ headers: {"X-CSRF-Token": $("#_csrf").val()} }); 

除了将“X-CSRF-Token”添加到post上的标题,你想完全禁用cookie!

var csrfProtection = csurf({cookie:false});

作者在这里提到https://github.com/expressjs/csurf/issues/52

cookie和会话validation不应该结合在一起 – 虽然这是有点误导,因为他已经在他的文档中结合了Cookie和会话validation: https : //github.com/expressjs/csurf#simple-express-example