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