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

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

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

Для этого вы должны использовать суперагент . Это модуль нижнего уровня и используется 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 }); для 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 }); в 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 для выполнения аутентифицированных запросов.

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

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

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

Я предполагаю, что вы используете промежуточное ПО 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 его в 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 } из 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 . Это заставит запрос использовать куки-файл, который мы создали.

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

Давайте будем гением компьютера.