在NodeJS中使用CSRF

时间:2016-04-06 06:12:52

标签: javascript ajax node.js express csrf


我试图在我的NodeJS应用程序中使用csrf。 你可以看到下面的代码。当我运行此代码时,我得到" TypeError:req.csrfToken不是函数"错误。

我想为所有请求创建csrf令牌,并希望在ajax调用中检查csrf令牌。正如我所说我无法创建csrf令牌,我收到错误。另外如何在ajax调用中检查csrf令牌?

你能救我吗?
感谢

服务器端:

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

/*this line commented*/
//var csrfProtection = csrf({ cookie: false });
var app = express();

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

var parseForm = bodyParser.urlencoded({ extended: false });
app.use(cookieParser());

/*this line added*/
app.use(csrf({ cookie: false }));

app.use(session({
    genid: function (req) {
        return "lkgktktgjknvfndkj-dfgjnkdfkjgn-dfgdfg";
    },
    name: "mySecret",
    resave: false, // don't save session if unmodified
    saveUninitialized: false, // don't create session until something stored
    secret: 'thisIsASecret'
}));

app.use(express.static(path.join(__dirname, 'public')));

app.use(function (req, res, next) {
    res.locals.csrfToken = req.csrfToken();

    next();
});

app.get('/', /*csrfProtection,*/ function (req, res) {
    res.render('index')
});

app.post('/process', parseForm, /*csrfProtection,*/ function (req, res) {
    res.send('data is being processed')
});

Index.jade

meta(name="csrf-token", content="#{csrfToken}")
block content
    input(type="hidden" name="_csrf" value="#{csrfToken}")

    |Favorite color: <input type="text" name="favoriteColor">
    button(type="submit" id="sbmt") Submit

    script(src= "/javascripts/jquery-2.2.1.js")

    script.
        $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
          var token;
          if (!options.crossDomain) {
            token = $('meta[name="csrf-token"]').attr('content');
            if (token) {
                return jqXHR.setRequestHeader('X-CSRF-Token', token);
            }
          }
        });

        $("#sbmt").click(function (e) {
            e.preventDefault();
            $.post(
                "/process",
                {
                    //text: text,
                    _csrf : $('meta[name="csrf-token"]').attr('content')
                }, function (data) {
                    console.log(data);
                });
        });

2 个答案:

答案 0 :(得分:3)

你必须添加:

app.use(session({ ... });
// Add this after session
app.use(csrfProtection);

您需要在会话之后添加此内容here

  

如果您正在设置&#34; cookie&#34;选择非假值,然后你   必须在此模块之前使用cookie-parser。否则,你必须使用   此模块之前的会话中间件。例如:快递会话   cookie的会话

答案 1 :(得分:1)

调用csrf()会返回一个函数(source)。您需要use才能拥有它。你在教程中错过的是:

var csrfProtection = csrf({ cookie: true })
app.get('/form', csrfProtection, function(req, res) {
    // pass the csrfToken to the view
    res.render('send', { csrfToken: req.csrfToken() })
})

此处,实际调用csrfProtection,并将csrfToken方法添加到req。在另一个例子中有:

app.use(csrf({ cookie: true }))

这意味着所有路由将使用保护,因此没有它的帖子就不可能。

这取决于您的使用情况 - 如果您想要保护所有路由 - 全局使用它(app.use),否则请按照请求使用它(如第一个示例中所示)。

如果您尝试在索引路径中使用它,您将拥有它,因为您已将其用作中间件:

app.get('/', csrfProtection, function (req, res) {
    res.render('index')
});