【问题标题】:How to handle csrf tokens during testing of a backend api如何在测试后端 api 期间处理 csrf 令牌
【发布时间】:2018-07-01 07:00:48
【问题描述】:

在运行单元/集成测试时如何处理 csrf 中间件功能?我有一个位于 Express 后端 API 前面的 Angular Web 应用程序。所有的后端路由都挂载在 csrf 中间件之后,所以在测试过程中,我总是遇到ForbiddenError: invalid csrf token 错误。那么,哪一个看起来更合适:

  1. process.env.NODE_ENV=test 时不要启用 csrf 中间件
  2. 专门为测试环境公开一个单独的端点以 检索 csrf 令牌并将其包含在每个 request

示例 1

express.js

const isProd = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';

if (!isTest) {
  app.use(csrf());
}

myTest.js

it('should make a PATCH request', function() {
  // this would not throw any `invalid_csrf` token errors
  return request
    .patch('SOME_URL')
    .expect(200, 'some data')
});

示例 2

express.js

const isProd = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';

// CSRF token. Angular needs it to be named 'XSRF-TOKEN'
app.use(csrf());
app.use((req, res, next) => {
  const _csrf = req.csrfToken();

  res.cookie('XSRF-TOKEN', _csrf, {
    secure: isProd,
    httpOnly: isProd
  });

  res.locals._csrf = _csrf;
  return next();
});

const router = require('./router')(app);

router.js

if (isTest) {
  app.use('/test/csrf', (req, res) => {
    res.json({
      csrfToken: res.locals._csrf
    });
  });
}

myTest.js

const app = require('./app');
const request = require('supertest')(app);

// helper
const cookies = (res) => {
  return res.headers['set-cookie'].map((cookies) => {
    return cookies.split(';')[0]
  }).join(';')
};

describe('example PATCH', function() {
  let response;

  // Use test endpoint to retrieve csrf token
  beforeEach(async () => {
    response = await request.get('/test/csrf');
  });

  // csrf token included (mimicking a client-side request), this will not throw an `invalid_csrf` token
  it('should make a PATCH request with a token', function() {
    return request
      .patch('SOME_URL')
      .set('Cookie', cookies(response))
      .set({
        'xsrf-token': response.body.csrfToken,
      })
      .expect(200, 'some data');
  });
})

所以我的问题真的是:当我的前端 Angular 应用程序有后端 api 时,我在使用 csrf 中间件时使用哪种方法?

使用的库:

csurf:https://github.com/expressjs/csurf

supertest:https://github.com/visionmedia/supertest

【问题讨论】:

  • 如果你想unit测试你的后端,你应该可以模拟你的令牌。
  • 我猜这更像是一个“集成”测试
  • @cusejuice 您是否设法找到如何集成测试受 csrf 保护的 api?

标签: javascript node.js express integration-testing csrf


【解决方案1】:

这两种方法都有效,不过我也提出了方法 3。

由于csurf(基于csrf)中的令牌对时间不敏感,因此您始终可以使用一对预定义的秘密+令牌进行单元测试。

const Token = require('csrf')
const token = new token()
const csrfToken = token.create('test')
console.log(csrfToken) // gaabrhn3--fmoXcOhmwoS6noe1TYvaDHzpYY

myTest.js

request
  .patch('SOME_URL')
  .set('Cookie', '_csrf=test')
  .set({
    'xsrf-token': 'gaabrhn3--fmoXcOhmwoS6noe1TYvaDHzpYY',
  })
  .expect(200, 'some data');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 2018-01-19
    • 2021-02-19
    • 2013-07-29
    • 2013-05-05
    • 2018-07-17
    • 2017-04-16
    • 2014-08-20
    相关资源
    最近更新 更多