如何使用PassportvalidationSupertest请求?

我使用Passport.js进行身份validation(本地策略),并使用Mocha和Supertest进行testing。

我如何创build一个会话,并使用Supertest进行身份validation请求?

你应该使用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来进行身份validation的请求。

正如zeMirco所指出的那样,底层的superagent模块支持会话,为您自动维护cookie。 但是,可以使用supertestsuperagent.agent()function,通过未supertest的function。

只需使用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(); }); 

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

对不起,但build议的解决scheme都不适合我。

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

cookies案件根本不适用于我。

所以,我的解决scheme是:

如果您使用的是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(); }); }); }); 

您可能希望有一个帮助器function来validation用户:

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值传递给你的请求。 但是,无论出于何种原因(至less在我的testing中),supertest都不会在同一个testing中触发2个请求。 所以,我们必须进行逆向工程,以获得正确的cookie值。 首先,您需要使用模块来构build您的Cookie:

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

是的,这是丑陋的。 我把这些放在我的testing文件的顶部。

接下来,我们需要构buildcookie值。 我把它放在一个beforeEach用于需要authentication用户的testing:

 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链的一部分定义了我要“login”的用户。 session的结构是Passport(至less当前)如何将当前用户信息插入到会话中。

如果您使用的是基于Cookie的会话,那么带有"j:""s:"var val行将从Connect CookieSession中间件中剥离出来,Passport将回退。 最后,我们序列化cookie。 我把"session"放在那里,因为这就是我configurationcookie会话中间件的方式。 此外, App.config.cookieSecret是在别处定义的,它必须是您传递给Express / Connect CookieSession中间件的秘密。 我把它存入Test.cookie以便以后可以访问它。

现在,在实际testing中,您需要使用该cookie。 例如,我有以下testing:

 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。

现在你已经伪装你的应用程序,认为用户已经login,并且不必保持实际的服务器运行。