15

我正在使用 Express 框架使用 Node.js 编写一个小型 Web 应用程序。我正在使用 csrf 中间件,但我想为某些请求禁用它。这就是我将它包含在我的应用程序中的方式:

var express = require('express');
var app = express();

app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.cookieSession({secret: 'secret'}));
app.use(express.csrf());

我想设置一个没有 csrf 控件的 POST 路由。

4

4 回答 4

32

有几种可能的方法。你基本上需要了解什么是最简单最正确的规则来决定是否使用 csrf 中间件。如果您大部分时间都需要 csrf,除了一小部分请求模式的白名单,请按照我对条件日志中间件的答案中的示例进行操作(为方便起见,复制如下)。

var express = require("express");
var csrf = express.csrf();
var app = express.createServer();

var conditionalCSRF = function (req, res, next) {
  //compute needCSRF here as appropriate based on req.path or whatever
  if (needCSRF) {
    csrf(req, res, next);
  } else {
    next();
  }
}

app.use(conditionalCSRF);
app.listen(3456);

另一种方法可能是仅在特定路径上使用中间件,例如app.post('/forms/*', express.csrf()). 您只想找到一种表达方式,以便在使用或不使用中间件时使其干净。

于 2012-11-22T18:37:19.033 回答
2

由于 Express 中间件按顺序执行,因此您始终可以将语句放在代码中的 csrf() 语句之上。

像这样:

app.get '/ping', (req, res) -> res.status(200).end()
app.use csrf()

Express 将在您的 csrf 令牌设置之前返回。对于极少数端点(我只有一个适合此类别的端点),我发现这是一种更清洁的解决方案。

此外,在撰写本文时,上述答案的代码如下所示:

customCsrf = (req, res, next) ->
  if req?.url isnt '/ping'
    return csrf()(req, res, next)
  else
    return next()

app.use customCsrf

那个额外的(req,res,next)让我绊倒了一段时间,所以希望这对某人有所帮助。

于 2014-08-09T02:43:04.137 回答
1

dailyjs.com有一篇关于 csrf 和 express 的好文章。它基本上是这样工作的:

使用 csrf 中间件:

app.configure(function() {
  // ...
  app.use(express.csrf());
  // ..
});

创建一个自定义中间件,将局部变量token设置为 csrf 值:

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

在您想要的每条路线中使用您的自定义中间件:

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

在您的表单中创建一个包含 csrf 值的隐藏字段:

form(action='/contact', method='post')
  input(type='hidden', name='_csrf', value=token)
于 2012-11-22T21:25:10.837 回答
1

使用 express 应用级别的中间件将每个 HTTP 方法添加到忽略列表中,以确保默认情况下不会验证保护。

例如

const ignoredMethods = [
    'GET',
    'HEAD',
    'POST',
    'PUT',
    'DELETE',
    'OPTIONS'
]

const csrfInit = csurf({ignoredMethods, cookie: true });
app.use(csrfInit);

这会将 csrfToken() 方法注入到每个请求对象中,从而允许应用程序设置隐藏字段或可消耗的 cookie。

然后在你的 as 中间件中添加一个受保护的版本到所需的路由,并忽略不需要它的那些。

例如受保护

const csrfProtection = csurf({ cookie: true });


router.post('/api/foo', csrfProtection, (req, res, next) => ...

例如未受保护的

const csrfProtection = csurf({ cookie: true });


router.post('/api/foo', (req, res, next) => ...

这对我有用。

于 2021-02-22T16:26:24.317 回答