如何验证与护照Supertest请求?(How to authenticate Supertest

2019-07-17 11:50发布

我使用Passport.js认证(本地策略),并与摩卡和Supertest测试。

我怎样才能创建一个会话,并与Supertest认证的请求?

Answer 1:

您应该使用的SuperAgent了点。 它是低级别模块,并通过使用supertest 。 看看节坚持一个代理 :

var request = require('superagent');
var user1 = request.agent();
user1
  .post('http://localhost:4000/signin')
  .send({ user: 'hunter@hunterloftis.com', password: 'password' })
  .end(function(err, res) {
    // user1 will manage its own cookies
    // res.redirects contains an Array of redirects
  });

现在你可以使用user1进行认证的请求。



Answer 2:

作为zeMirco指出,潜在superagent模块支持会话,自动保持你的cookies。 然而,也可以使用superagent.agent()从功能supertest ,通过一个未记录的功能。

只需使用require('supertest').agent('url')而不是require('supertest')('url')

var request = require('supertest');
var server = request.agent('http://localhost:3000');

describe('GET /api/getDir', function(){
    it('login', loginUser());
    it('uri that requires user to be logged in', function(done){
    server
        .get('/api/getDir')                       
        .expect(200)
        .end(function(err, res){
            if (err) return done(err);
            console.log(res.body);
            done()
        });
    });
});


function loginUser() {
    return function(done) {
        server
            .post('/login')
            .send({ username: 'admin', password: 'admin' })
            .expect(302)
            .expect('Location', '/')
            .end(onResponse);

        function onResponse(err, res) {
           if (err) return done(err);
           return done();
        }
    };
};


Answer 3:

试试这个,

  var request=require('supertest');
  var cookie;
  request(app)
  .post('/login')
  .send({ email: "user@gluck.com", password:'password' })
  .end(function(err,res){
    res.should.have.status(200);
    cookie = res.headers['set-cookie'];
    done();        
  });

  //
  // and use the cookie on the next request
  request(app)
  .get('/v1/your/path')
  .set('cookie', cookie)
  .end(function(err,res){  
    res.should.have.status(200);
    done();        
  });


Answer 4:

作为附录安迪的回答,才能有Supertest启动你的服务器,你可以做到这一点是这样的:

var request = require('supertest');

/**
 * `../server` should point to your main server bootstrap file,
 * which has your express app exported. For example:
 * 
 * var app = express();
 * module.exports = app;
 */
var server = require('../server');

// Using request.agent() is the key
var agent = request.agent(server);

describe('Sessions', function() {

  it('Should create a session', function(done) {
    agent.post('/api/session')
    .send({ username: 'user', password: 'pass' })
    .end(function(err, res) {
      expect(req.status).to.equal(201);
      done();
    });
  });

  it('Should return the current session', function(done) {
    agent.get('/api/session').end(function(err, res) {
      expect(req.status).to.equal(200);
      done();
    });
  });
});


Answer 5:

我很抱歉,但没有建议的解决方案并不为我工作。

随着supertest.agent()我不能使用的app实例,我需要事先运行服务器,并指定http://127.0.0.1:port ,而且我不能使用supertest的预期(断言),我不能使用supertest-as-promised lib和等等...

cookies情况下也不会在所有的工作对我来说。

所以,我的解决办法是:

如果您正在使用Passport.js,它利用了“承载令牌”机制,您可以在您的规格使用下面的例子:

var request = require('supertest');
var should = require('should');

var app = require('../server/app.js'); // your server.js file

describe('Some auth-required API', function () {
  var token;

  before(function (done) {
    request(app)
      .post('/auth/local')
      .send({
        email: 'test@example.com',
        password: 'the secret'
      })
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        res.body.should.to.have.property('token');
        token = res.body.token;

        done();
      });
  });

  it('should respond with status code 200 and so on...', function (done) {
    request(app)
      .get('/api/v2/blah-blah')
      .set('authorization', 'Bearer ' + token) // 1) using the authorization header
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        // some `res.body` assertions...

        done();
      });
  });

  it('should respond with status code 200 and so on...', function (done) {
    request(app)
      .get('/api/v2/blah-blah')
      .query({access_token: token}) // 2) using the query string
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        // some `res.body` assertions...

        done();
      });
  });
});

您可能希望有一个辅助函数来验证用户:

test/auth-helper.js

'use strict';

var request = require('supertest');
var app = require('app.js');

/**
 * Authenticate a test user.
 *
 * @param {User} user
 * @param {function(err:Error, token:String)} callback
 */
exports.authenticate = function (user, callback) {
  request(app)
    .post('/auth/local')
    .send({
      email: user.email,
      password: user.password
    })
    .end(function (err, res) {
      if (err) {
        return callback(err);
      }

      callback(null, res.body.token);
    });
};

有一个富有成效的一天!



Answer 6:

我会假设你正在使用的CookieSession中间件。

作为平头提到的,你的目标是获得一个cookie值传递到您的要求。 然而,无论出于何种原因(至少在我的测试),supertest将不会触发在同一个测试2个请求。 所以,我们必须进行逆向工程如何得到正确的cookie的值。 首先,你需要为需要构建您的Cookie模块:

var Cookie          = require("express/node_modules/connect/lib/middleware/session/cookie")
  , cookieSignature = require("express/node_modules/cookie-signature")

是的,这是丑陋的。 我把那些在我的测试文件的顶部。

接下来,我们需要构建的cookie的值。 我把这个变成一个beforeEach对于需要身份验证的用户测试:

var cookie = new Cookie()
  , session = {
      passport: {
        user: Test.user.id
      }
    }

var val = "j:" + JSON.stringify(session)
val = 's:' + cookieSignature.sign(val, App.config.cookieSecret)
Test.cookie = cookie.serialize("session",val)

Test.user.id在我的部分是以前定义beforeEach是定义我要“登录”用户链。 的结构session是护照(至少目前)如何插入当前用户信息到您的会话。

var val线, "j:""s:"都拆出来连接CookieSession中间件的护照将回退到上,如果你正在使用基于Cookie的会话。 最后,我们序列化饼干。 我把"session"在那里,因为这是我如何配置我的Cookie会话中间件。 此外, App.config.cookieSecret在别处定义,它必须是传递给您的快递/连接CookieSession中间件的秘密。 我藏入Test.cookie ,这样我以后可以访问它。

现在,在实际测试中,你需要使用的cookie。 例如,我有以下测试:

it("should logout a user", function(done) {
  r = request(App.app)
    .del(App.Test.versionedPath("/logout"))
    .set("cookie", Test.cookie)
    // ... other sets and expectations and your .end
}

注意调用set"cookie"Test.cookie 。 这将导致使用我们构建的cookie中的请求。

现在你已经伪造了您的应用程序,以为用户登录,和你没有保持一个实际的服务器上运行。



文章来源: How to authenticate Supertest requests with Passport?