Как аутентифицировать запросы Supertest с паспортом?


Я использую паспорт.js для аутентификации (локальная стратегия) и тестирования с помощью Mocha и Supertest.

Как я могу создать сеанс и сделать аутентифицированные запросы с помощью Supertest?

6 57

6 ответов:

вы должны использовать суперагент для этого. Это модуль более низкого уровня и используется 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 сделать проверку подлинности запросов.

как указывает земирко, лежащий в основе superagent модуль поддерживает сеансы, автоматически поддерживая печенье для вас. Тем не менее, можно использовать 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();
        }
    };
};

попробуйте это,

  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();        
  });

в качестве дополнения к ответу Энди, чтобы иметь 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();
    });
  });
});

извините, но ни одно из предложенных решений не работает для меня.

С supertest.agent() Я не могу использовать app экземпляр, я должен запустить сервер заранее и указать http://127.0.0.1:port и более того, я не могу использовать ожидания supertest (утверждения), я не могу использовать supertest-as-promised lib и так далее...

The cookies дело не будет работать для меня вообще.

Итак, мое решение:

если вы используете паспорт.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);
    });
};

удачного Вам дня!

я предполагаю, что вы используете промежуточное программное обеспечение CookieSession.

как упоминал grub, ваша цель-получить значение 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 был ранее определен в части my beforeEach цепь, которая определила пользователя, которого я собирался "войти". Структура session как Passport (по крайней мере в настоящее время) вставляет текущую информацию о пользователе в ваш сеанс.

The var val строки с "j:" и "s:" несколько вырвано из промежуточного программного обеспечения Connect CookieSession, которое Passport будет резервным, если вы используете сеансы на основе файлов cookie. Наконец, мы сериализуем куки. Я ставлю "session" там, потому что именно так я настроил свое промежуточное программное обеспечение сеанса cookie. Кроме того,App.config.cookieSecret определяется в другом месте, и это должен быть секрет, который вы передаете своему промежуточному программному обеспечению Express/Connect CookieSession. Я прячу его в Test.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, который мы создали.

и теперь вы подделали свое приложение, думая, что пользователь вошел в систему, и вам не нужно поддерживать фактический сервер.