Node.js在使用Express 4时如何有条件地使用csurf?

8

我想在我的Express应用程序中只对少数路由使用csurf。

以下是做法:

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

// some more stuff

var csrfExclusion = ['/myApi','/unsecure'];

var app   = express();

var conditionalCSRF = function (req, res, next) {  
  if (csrfExclusion.indexOf(req.path) !== -1){
    next();
  }
  else{
    csrf();
  }
});

app.use(conditionalCSRF);

甚至尝试过:

var conditionalCSRF = function (req, res, next) {  
  if (csrfExclusion.indexOf(req.path) !== -1){
    next();
  }
  else{
    csrf(req, res, next);
    next();
  }
});

并且

var conditionalCSRF = function (req, res, next) {  
  if (csrfExclusion.indexOf(req.path) !== -1){
    next();
  }
  else{
    csrf();
    next();
  }
});

但是这会给我一个错误:对象#没有方法'csrfToken'

如何有条件地使用csurf。文档只提供在express应用程序的所有路由中使用它的信息

app.use(csrf());

但这不是我想要的,我想要排除一些路由...

亲切地... 马丁

更新:

最终它起作用了。我做了以下几点:

app.use(function(req, res, next){
  if (csrfExclusion.indexOf(req.path) !== -1) {
  next();
}
  else {
  csrf()(req, res, next);
});

这个条件性地添加了 csrf 中间件。但我认为这样命名有点奇怪:
csrf()(req, res, next);

我甚至不理解语法...


感谢您分享您的发现,您也可以为此编写一个单独的答案。无论如何,我想分享目前存在一些情况,似乎不可能免除csrf。开放问题:https://github.com/expressjs/csurf/issues/10#issuecomment-232501314 - Wtower
2个回答

6

根据这个,你需要将其拆分为两个路由器,一个使用csurf,另一个不使用。然后将中间件应用于路由器而不是应用程序。

var routes = express.Router();
var csrfExcludedRoutes = express.Router();

routes.use(csrf());

routes.get('/', function(req, res) {
    //has req.csrfToken()
});

csrfExcludedRoutes.get('/myApi', function(req, res) {
    //doesn't have req.csrfToken()
});

谢谢提供这个链接...这个也可能起作用..我现在正在使用所描述的解决方案... - marschro
2
我无法让这个建议的解决方案起作用,但原帖作者在他的更新中描述的那个解决方案管用。 - napu

2
这是一个旧的线程,但我偶然发现了它,并想尝试回答@marshro提出的问题,即在中间件中调用 csrf()(req, res, next) 的奇怪性质。
这里发生的情况是,csurf从require语句返回一个函数,该函数本身用于构建一个带有一些可选配置参数的中间件函数。
上面中间件中使用的csrf()调用为每个需要CSRF保护的传入请求构建具有默认选项的中间件函数。如果您真的想使用此方法,您确实有机会进行简单的更改以使您的解决方案更有效率,只需进行非常小的重构即可构建中间件一次:
// 1. Build the csrf middleware function 'csrfMw' once.
var csrfMw = csrf();          

app.use(function(req, res, next){
    if (csrfExclusion.indexOf(req.path) !== -1) {
        next();
    } else {
        // 2. Use the middleware function across all requests.
        csrfMw(req, res, next);  
    }
);

话虽如此,当你有机会再次查看文档时,你可能会想要了解两种推荐的避免此方法的方法。第一种设置中间件csrfProtection并将其应用于选择的路由。第二种设置两个路由器,如上面提到的@ben-fortune - 一个将csrf应用于所有内容,另一个则不应用。这两种方法都比具有排除条件更有效。

尽管如此,我可以看出有排除列表的情况,并且如果我没有时间手动分解路由,则可以使用您的方法。 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接