使用Mocha、Chai、SuperTest测试XSRF-TOKEN无效响应问题
问题分析与修复方案
你的测试代码存在两个核心问题,导致CSRF Token验证失败:
- 两次请求使用独立的
request(app)实例,Cookie无法在会话间共享,后端CSRF中间件需要验证Cookie与请求头中的Token是否匹配,而第二次请求未携带正确的Cookie。 - 请求头设置错误,多数CSRF中间件(如Express的
csurf)要求的是X-XSRF-TOKEN头,而非XSRF-TOKEN,且手动往Cookie中塞入XSRF-TOKEN属于多余操作。
修复步骤
- 复用SuperTest Agent实例:使用
request.agent(app)创建持久化会话,自动管理Cookie,模拟浏览器的会话行为。 - 修正CSRF请求头:将请求头改为
X-XSRF-TOKEN,无需手动设置Cookie,Agent会自动携带第一次请求获取的Cookie。 - 优化测试结构:用
before钩子提前获取CSRF Token,确保登录测试执行时Token已准备就绪。
修改后的完整代码
const app = require('../../../app.js'); const expect = require('chai').expect; const request = require('supertest'); // 创建持久化Agent实例,自动维护会话Cookie const agent = request.agent(app); let csrfToken; describe('用户登录流程测试', () => { // 所有测试执行前先获取CSRF Token before((done) => { agent.get('/api/csrf-token') .expect(200) .then((res) => { csrfToken = res.body.csrfToken; expect(res.body).to.have.property('csrfToken'); done(); }) .catch(done); }); it('使用超级管理员凭证登录', (done) => { agent.post('/api/users/login') // 设置符合规范的CSRF请求头 .set('X-XSRF-TOKEN', csrfToken) .send({ email: 'super@abc.com', password: 'abc' }) .then((res) => { const body = res.body; console.log(body); // 修正断言逻辑:message是字符串,直接判断内容 expect(body.message).to.include('Auth Successful'); expect(body).to.have.property('token'); done(); }) .catch(done); }); });
关键改动说明
- 用
request.agent(app)替代单次request(app),保证Cookie在整个会话中自动共享。 - 移除手动设置Cookie的代码,Agent会自动携带第一次请求返回的Cookie。
- 将请求头改为
X-XSRF-TOKEN,匹配大多数CSRF中间件的验证要求。 - 修正断言逻辑:原代码中
expect(body.message).to.contain.property('Auth Successful')错误,因为message是字符串而非对象,改为to.include直接判断字符串内容。
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

