Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Вам следует использовать superagent. Это модуль нижнего уровня и используется supertest. Взгляните на раздел Сохранение агента:

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

Теперь вы можете использовать user1 для выполнения аутентифицированных запросов.

Ответ 2

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

Ответ 3

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

  var request=require('supertest');
  var cookie;
  request(app)
  .post('/login')
  .send({ email: "[email protected]", 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();        
  });

Ответ 4

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

Ответ 5

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

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

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

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

Если вы используете Passport.js, в нем используется механизм маркера Bearer, и вы можете использовать следующие примеры в своих спецификациях:

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: '[email protected]',
        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);
    });
};

Иметь продуктивный день!

Ответ 6

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

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

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