2016-09-30 76 views
0

我正尝试使用Mocha,Chai和ChaiHttp在我的Express应用程序中编写POST路由的测试,但由于事实上我无论何时提交我的CSRF令牌都会收到​​响应,我无法正常工作。下面是我到目前为止的代码:NodeJS Express应用程序测试 - 如何在使用Mocha和Chai进行测试时提交CSRF令牌?

express.js配置文件

... 
    app.use(session(config.SESSION)); 
    // csrf is the 'csurf' module 
    app.use(csrf()); 

    app.use((req, res, next) => { 
    res.cookie('XSRF-TOKEN', req.csrfToken()); 
    return next(); 
    }); 
... 

User.test.js

'use strict'; 
process.env.NODE_ENV = 'test'; 

const User = require('../server/models/User'); 
const chai = require('chai'); 
const chaiHttp = require('chai-http'); 
const server = require('../index'); 
const utils = require('../utils'); 

chai.use(chaiHttp); 

describe('Users',() => { 
    beforeEach((done) => { 
    User.remove({}, (err) => { 
     done(); 
    }); 
    }); 

    after((done) => { 
    server.close(); 
    done(); 
    }); 
... 
/* 
    * [POST] /user 
    */ 
    describe('[POST] /user',() => { 
    it('should return a JSON object with a "success" property equal to "true" when creating a new user', (done) => { 
     const userObj = utils.generateUserObject(); 

     chai.request(server) 
      .get('/api') 
      .end((error, response) => { 

      userObj._csrf = utils.extractCsrfToken(response.headers['set-cookie']); 


      /* 
      * Accurately logs the _csrf property with the correct CSRF token that was retrieved via the initial GET request 
      * 
      * Example output: 
      * 
      * { 
      * username: 'Stacey89', 
      * first_name: 'Gregg', 
      * last_name: 'King', 
      * ... 
      * _csrf: 'vBhDfXUq-jE86hOHadDyjgpQOu-uE8FyUp_M' 
      * } 
      * 
      */ 


      console.log(userObj); 

      chai.request(server) 
       .post('/api/user') 
       .set('content-type', 'application/x-www-form-urlencoded') 
       .send(userObj) 
       .end((err, res) => { 
        res.should.have.status(200); 
        res.body.should.be.a('object'); 
        res.body.should.have.property('success').eql('true'); 
        done(); 
       }); 
      }); 
    }); 
... 

utils.js

... 
    extractCsrfToken(cookiesObj) { 
    const cookiesArray = Array.prototype.join.call(cookiesObj, '').split(';'); 
    let csrfToken = 'NOT FOUND'; 

    cookiesArray.forEach((cookie) => { 
     if (cookie.includes('XSRF-TOKEN')) { 
     csrfToken = cookie.split('=').splice(1, 1).join(''); 
     } 
    }); 

    return csrfToken; 
    } 
... 

当我运行上面的测试,我得到以下错误:

ForbiddenError: invalid csrf token 
... 
POST /api/user 403 

奇怪的是,如果我从邮递员用完全相同的配置如前所述的一个POST请求,我顺利拿到回应我正在寻找和表单提交成功。

从我的测试套件中提交userObj似乎不工作。

UPDATE#1 我终于设法找到了适合我的问题的解决方案。

我已经更新了先前的XSRF-TOKEN的cookie设置为以下中间件:

app.use((err, req, res, next) => { 
    res.locals._csrf = req.csrfToken(); 
    return next(); 
    }); 

现在的单元测试运行成功。

此外,我注意到,向服务器发出第一[GET]请求返回Set-Cookie头:

Status Code: 200 OK 
Content-Length: 264 
Content-Type: application/json; charset=utf-8 
Date: Tue, 18 Oct 2016 12:10:09 GMT 
Etag: W/"108-NSQ2HIdRqiuMIf0F+7qwjw" 
Set-Cookie: connect.sid=s%3Ap5io8_3iD7Wy0X0K77qWZLoYj-fD1ZbA.6uvcBiB%2B%2BSi1KOVOmJgvWe%2B5Mqpuc1rs9yUYxH0uNPY; Path=/; HttpOnly 
X-Download-Options: noopen 
X-XSS-Protection: 1; mode=block 
x-content-type-options: nosniff 
x-dns-prefetch-control: off 
x-frame-options: SAMEORIGIN 

任何后续[GET]请求不返回头:

Status Code: 200 OK 
Content-Length: 264 
Content-Type: application/json; charset=utf-8 
Date: Tue, 18 Oct 2016 12:11:19 GMT 
Etag: W/"108-NSQ2HIdRqiuMIf0F+7qwjw" 
X-Download-Options: noopen 
X-XSS-Protection: 1; mode=block 
x-content-type-options: nosniff 
x-dns-prefetch-control: off 
x-frame-options: SAMEORIGIN 

这是正常的应用安全条款?只需在res.locals对象上设置_csrf标记是否是一种很好的做法?

回答

0

chai-http的send()方法用于发送json(通常需要使用json主体解析器)。因此,您不应该将内容类型设置为application/x-www-form-urlencoded

如果你没有使用JSON解析器身体和你真的想寄的表格数据,该field() method应该工作:

chai.request(server) 
    .post('/api/user') 
    .field('_csrf', _csrf) 
    .end((err, res) => { 
     res.should.have.status(200); 
     res.body.should.be.a('object'); 
     res.body.should.have.property('success').eql('true'); 
     done(); 
    }); 
+0

我并不想通过cookie来把它 - 我发送_csrf标记作为'req.body'的一部分 –

相关问题