当前位置: 首页 > 面试题库 >

如何在node.js / express中测试受csrf保护的端点

尤研
2023-03-14
问题内容

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

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

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

我的问题是测试这些api端点。我正在使用mocha来运行自动化测试,并使用request模块来测试api端点。当我通过请求模块向使用csrf(POST,PUT,DELETE等)的端点发出请求时,即使它正确利用了cookie等,它也会失败。

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

测试示例:

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();
  });
}

问题答案:

诀窍是您需要将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;
  next();
})

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

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();
  });
});

这个想法是实际登录并使用您从cookie获得的CSRF令牌。请注意,您需要在mocha测试文件的顶部执行以下操作:

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


 类似资料:
  • 简介 Laravel 可以轻松地保护应用程序免受 跨站点请求伪造 (CSRF) 攻击,跨站点请求伪造是一种恶意攻击,它凭借已通过身份验证的用户身份来运行未经过授权的命令。 Laravel 会自动为每个活跃用户的会话生成一个 CSRF「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。 无论何时,当您在应用程序中定义HTML表单时,都应该在表单中包含一个隐藏的CSRF标记字段,

  • CSRF是指针对Web应用程序的跨站点伪造攻击。 CSRF攻击是系统的经过身份验证的用户执行的未授权活动。 因此,许多Web应用程序容易受到这些攻击。 Laravel以下列方式提供CSRF保护 - Laravel包含一个内置的CSRF插件,可为每个活动用户会话生成令牌。 这些令牌验证相关的经过身份验证的用户是否发送了操作或请求。 实现 (Implementation) 本节将详细讨论Laravel

  • 问题内容: 试图使用EasyMock来测试是否调用了一个受保护的方法,不知道这是否是最好的方法……但是鉴于以下内容,我如何才能知道在调用callMe()时didIgetCalled()实际上是被调用了? 问题答案: 这是一种无需使用EasyMock即可测试该方法的方法,但是我的建议是:如果它不是公开的,请不要为此编写测试 我知道这不会完全解决您的问题,但这只是一个开始 :)

  • 问题内容: 关键字授予对相同包和子类(http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html)中的类的访问权限。 现在,每个类都有一个超类(http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)。 因此,我得出结论,即使每个类都可以访问的方法。

  • 在发送请求之前(当单元测试时),我是否可以得到csrf令牌?

  • 我正在使用Spring构建Web应用程序。我有多个Spring客户端应用程序和一个OAuth2授权和资源服务器。最终用户首先在客户端应用内进行身份验证,然后客户端应用从资源服务器请求一些资源(从授权服务器获得访问令牌后),处理数据并将其返回给用户。用户也可以更改资源服务器上的数据,但只能通过客户端应用。对于仅使用客户端凭证的资源获取,在这种情况下资源所有者是可信客户端。 在资源服务器上,仅存储客户