0

我正在尝试使用 jest(测试环境:节点)通过集成测试,以获得使用 csurf 进行 csrf 保护的登录表单(使用 cookie 选项)。

我已经从登录表单和 set-cookie 标头中提取了 csrfToken,但测试仍然失败,并出现 403 - 无效 csrf 令牌。

我看不出问题出在哪里,希望能朝着正确的方向前进。

测试文件:

const request   = require('supertest');
const {User}    = require('../../server/models/user');
const cheerio   = require('cheerio');
const app       = require('../../app');

let user, csrfToken, password, cookies;

beforeEach( async () => {
  user = await new User({
    firstName: "Name",
    lastName: "Surname",
    email: "email@example.com",
    password: "password",
    isAdmin : true
  }).save();
});

afterEach( async () => {
  await User.deleteMany();
});

describe('/login', () => {

  describe('GET /', () => {

    const exec = async () => {
      const res = await request(app).get(`/login`);
      let $ = cheerio.load(res.text);
      csrfToken = $('[name=_csrf]').val();
      return res;
    };

    it('should return the login form', async () => {
      const res = await exec();
      expect(res.status).toBe(200);
      expect(res.text).toMatch(/Sign In/);
    });
  });

  describe('POST /', () => {

    const getLoginCsrfs = async () => {
      const res = await request(app).get(`/login`);
      let $ = cheerio.load(res.text);
      csrfToken = $('[name=_csrf]').val();
      cookies = res.headers['set-cookie'];
      return res;
    };

    const postLogin = async () => {
      return request(app).post(`/login`)
        .set('Cookie', cookies)
        .send({ email: user.email,
                password: password,
                _csrf: csrfToken
        });
    };

    it('should return 401 without incorrect user info', async () => {
      await getLoginCsrfs();
      password = 'wrongpassword';
      const res = await postLogin();
      expect(res.status).toBe(401)
    });

    it('should return 403 without csrf token/header credentials', async () => {
      await getLoginCsrfs();
      csrfToken = '';
      cookies = '';
      password = 'password';
      const res = await postLogin();
      expect(res.status).toBe(403)
    });

    it('should return 200 with correct credentials', async () => {
      await getLoginCsrfs();
      password = 'password';
      const res = await postLogin();
      expect(res.status).toBe(200)
    });
  });
});
 FAIL  tests/integration/login.test.js
  /login
    GET /
      ✓ should return the login form (300ms)
    POST /
      ✕ should return 401 without incorrect user info (150ms)
      ✓ should return 403 without csrf token/header credentials (130ms)
      ✕ should return 200 with correct credentials (131ms)

  ● /login › POST / › should return 401 without incorrect user info

    expect(received).toBe(expected) // Object.is equality

    Expected: 401
    Received: 403

      61 |       password = 'wrongpassword';
      62 |       const res = await postLogin();
    > 63 |       expect(res.status).toBe(401)
         |                          ^
      64 |     });
      65 |
      66 |     it('should return 403 without csrf token/header credentials', async () => {

      at Object.toBe (tests/integration/login.test.js:63:26)

  ● /login › POST / › should return 200 with correct credentials

    expect(received).toBe(expected) // Object.is equality

    Expected: 200
    Received: 403

      77 |       password = 'password';
      78 |       const res = await postLogin();
    > 79 |       expect(res.status).toBe(200)
         |                          ^
      80 |     });
      81 |   });
      82 | });

      at Object.toBe (tests/integration/login.test.js:79:26)

4

1 回答 1

0

最初我认为与 set-cookie 中的 _csrf 相关的问题,但在重新检查解决方案后很简单,

    const postLogin = async () => {
      return request(app).post(`/login`)
        .type('form')
        .set('Cookie', cookies)
        .send({ email: user.email,
                password: password,
                _csrf: csrfToken
        });
    };

我省略了 .type('form'),与表单中的 csrfToken 相关的 403(所有表单数据),没有被看到。

 PASS  tests/integration/login.test.js (5.661s)
  /login
    GET /
      ✓ should return the login form (489ms)
    POST /
      ✓ should return 401 without incorrect user info (443ms)
      ✓ should return 403 without csrf token/header credentials (131ms)
      ✓ should return 200 with correct credentials (255ms)

我一直在谷歌搜索,并考虑了与开玩笑/超级测试和多个 cookie 相关的问题,但与以往一样,解决方案更加直接且离家更近。

于 2019-02-17T02:13:32.437 回答