如何在 node.js/express 中测试受 csrf 保护的端点 [英] How to test endpoints protected by csrf in node.js/express

查看:23
本文介绍了如何在 node.js/express 中测试受 csrf 保护的端点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经以如下方式实现了 csrf(跨站点请求伪造)保护:

<预><代码>...app.use(express.csrf());app.use(function (req, res, next) {res.cookie('XSRF-TOKEN', req.csrfToken());下一个();});...

这很好用.Angularjs 在通过 $http 服务发出的所有请求中都使用了 csrf 令牌.我通过 Angular 应用发出的请求效果很好.

我的问题是测试这些 api 端点.我使用 mocha 运行我的自动化测试和请求模块来测试我的 api 端点.当我使用请求模块向使用 csrf(POST、PUT、DELETE 等)的端点发出请求时,它会失败,即使它正确地使用了 cookie 等.

有没有其他人想出解决方案?有人需要更多信息吗?

测试示例:

function testLogin(done) {要求({方法:'POST',url: baseUrl + '/api/login',json:{电子邮件:'myemail@email.com',密码:'我的密码'}}, 函数 (err, res, body) {//做一些事情来验证返回的数据//服务器返回一个 'FORBIDDEN' 字符串,//这显然不会通过我的验证//标准完毕();});}

解决方案

诀窍是您需要将 POST 测试包装在 GET 中,并从 cookie 中解析必要的 CSRF 令牌.首先,假设您创建了一个与 Angular 兼容的 CSRF cookie,如下所示:

.use(express.csrf()).use(function (req, res, next) {res.cookie('XSRF-TOKEN', req.session._csrf);res.locals.csrftoken = req.session._csrf;下一个();})

然后,您的测试可能如下所示:

describe('Authenticated Jade tests', function () {this.timeout(5000);之前(功能(完成){[在此处设置经过身份验证的用户]});var validPaths = ['/help', '/products'];async.each(validPaths, function (path, callback) {it('应该确认' + path + ' 提供 HTML 并且仅在登录时可用', function (done) {request.get('https://127.0.0.1:' + process.env.PORT + path, function (err, res, body) {期望(res.statusCode).to.be(302);期望(res.headers.location).to.be('/login');expect(body).to.be('暂时移动.重定向到/login');var csrftoken = unescape(/XSRF-TOKEN=(.*?);/.exec(res.headers['set-cookie'])[1]);var authAttributes = { _csrf: csrftoken, email: userAttributes.email, password: 'password' };request.post('https://127.0.0.1:' + process.env.PORT + '/login', { body: authAttributes, json: true }, function (err, res) {期望(res.statusCode).to.be(303);request.get('https://127.0.0.1:' + process.env.PORT + path, function (err, res, body) {期望(res.statusCode).to.be(200);期望(body.toString().substr(-14)).to.be('</body></html>');request.get('https://127.0.0.1:' + process.env.PORT + '/bye', function () {完毕();});});});});});打回来();});});

我们的想法是实际登录并使用您从 cookie 中获取的 CSRF 令牌.请注意,您需要在 mocha 测试文件的顶部添加以下内容:

var request = require('request').defaults({jar: true, followRedirect: false});

I have implemented csrf (cross-site request forgery) protection in an express like so:

...
app.use(express.csrf());
app.use(function (req, res, next) {
  res.cookie('XSRF-TOKEN', req.csrfToken());
  next();
});
...

This works great. Angularjs utilized the csrf token in all requests made through the $http service. The requests that I make through my angular app work great.

My problem is testing these api endpoints. I'm using mocha to run my automated tests and the request module to test my api endpoints. When I make a request to an endpoint that utilizes csrf (POST, PUT, DELETE, etc.) using the request module, it fails, even though it correctly utilizes cookies and such.

Has anybody else come up with a solution to this? Does anyone need more information?

Example of test:

function testLogin(done) {
  request({
    method: 'POST',
    url: baseUrl + '/api/login',
    json: {
      email: 'myemail@email.com',
      password: 'mypassword'
    } 
  }, function (err, res, body) {
    // do stuff to validate returned data
    // the server spits back a 'FORBIDDEN' string,
    // which obviously will not pass my validation
    // criteria
    done();
  });
}

解决方案

The trick is that you need to wrap your POST test inside a GET and parse the necessary CSRF token from the cookie. First, this assumes you create an Angular-compatible CSRF cookie like this:

.use(express.csrf())
.use(function (req, res, next) {
  res.cookie('XSRF-TOKEN', req.session._csrf);
  res.locals.csrftoken = req.session._csrf;
  next();
})

Then, your test could look like this:

describe('Authenticated Jade tests', function () {
  this.timeout(5000);

  before(function (done) {
    [Set up an authenticated user here]
  });

  var validPaths = ['/help', '/products'];

  async.each(validPaths, function (path, callback) {
    it('should confirm that ' + path + ' serves HTML and is only available when logged in', function (done) {
      request.get('https://127.0.0.1:' + process.env.PORT + path, function (err, res, body) {
        expect(res.statusCode).to.be(302);
        expect(res.headers.location).to.be('/login');
        expect(body).to.be('Moved Temporarily. Redirecting to /login');

        var csrftoken = unescape(/XSRF-TOKEN=(.*?);/.exec(res.headers['set-cookie'])[1]);
        var authAttributes = { _csrf: csrftoken, email: userAttributes.email, password: 'password' };

        request.post('https://127.0.0.1:' + process.env.PORT + '/login', { body: authAttributes, json: true }, function (err, res) {
          expect(res.statusCode).to.be(303);

          request.get('https://127.0.0.1:' + process.env.PORT + path, function (err, res, body) {
            expect(res.statusCode).to.be(200);
            expect(body.toString().substr(-14)).to.be('</body></html>');

            request.get('https://127.0.0.1:' + process.env.PORT + '/bye', function () {
              done();
            });
          });
        });
      });
    });

    callback();
  });
});

The idea is to actually login and use post the CSRF token you're getting from the cookie. Note that you need the following at the top of the mocha test file:

var request = require('request').defaults({jar: true, followRedirect: false});

这篇关于如何在 node.js/express 中测试受 csrf 保护的端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆