鉴于此策略:
var strategy = new LocalStrategy( { session: true },function (username,password,done) { User.findOne({ username: username },function(err,user) { if (err) { return done(err); } if (!user) { return done(null,false,{ message: 'Incorrect username.' }); } if (user.password !== password) { return done(null,{ message: 'Incorrect password.' }); } return done(null,user); }); });
而这台服务器:
//************ EDIT ****// function genuuid(req) { return "Test UID"; } //************ EDIT ****// var app = express(); var router = express.Router(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(passport.initialize()); //************ EDIT ****// app.use(session({ genid: function(req) { return genuuid() // use UUIDs for session IDs },secret: "somethingSecret",cookie: {maxAge: 60000 },resave: true,saveUninitialized: false })); //************ EDIT ****// passport.use(strategy); passport.serializeUser(function(user,done) { done(null,user.id); }); passport.deserializeUser(function(id,done) { User.findById(id,user) { done(err,user); }); }); app.post('/login',passport.authenticate('local',{ successRedirect: '/',failureRedirect: '/login' })); server = http.createServer(app).listen(port,function(){ console.log('Express server listening on port ' + app.get('port')); })
it('Login should redirect to home and return a user token',function(done) { var postData = querystring.stringify({ username : user,password : password }); var options = { uri: 'http://' + hostname + ':' + port + '/login',followRedirect: false }; request.post(options) .form(postData) .on('response',function(res) { res.statusCode.should.equal(302); }) .on('data',function(data) { should.exist(data); should.fail(0,1,'Test not implemented'); done(); }) .on('error',function(e) { should.fail(0,'Problem with request: ' + e.message); }); });
标题包含
{ 'x-powered-by': 'Express',location: '/',vary: 'Accept','content-type': 'text/plain; charset=utf-8','content-length': '35',date: 'Tue,08 Sep 2015 19:46:03 GMT',connection: 'keep-alive' }
没有饼干或其他什么.我的代币在哪里?
解决方法
var session = require('express-session'); // Code to set up your app var app = express(); // Make sure to replace "somethingSecret" with your own secret value app.use(session({secret: "somethingSecret",saveUnitialized: false}));
我写了一个非常接近你提供的应用程序的应用程序,看到了同样的问题,这对我来说很奇怪,因为我以前曾多次使用过快递和护照.当我意识到我没有使用任何会话中间件时,我添加了快速会话中间件和瞧; set-cookie标头.
但请注意,此代码实际上尚未准备好进行生产.从快速会话存储库:
Warning The default server-side session storage,MemoryStore,is purposely not designed for a production environment. It will leak memory under most conditions,does not scale past a single process,and is meant for debugging and developing.
For a list of stores,see 07001.
[编辑]
var bodyParser = require('body-parser'); var express = require('express'); var http = require('http'); var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; var session = require('express-session'); // Stub of User schema for testing var User = { findOne: function(user,callback) { callback(null,{ id: 1234,username: user.username,password: 'foo' }); },findById: function(id,username: 'user',password: 'foo' }); } }; var strategy = new LocalStrategy( { session: true },user); }); }); function genuuid(req) { return "Test UID"; } var app = express(); var router = express.Router(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(passport.initialize()); app.use(session({ genid: function(req) { return genuuid() // use UUIDs for session IDs },saveUninitialized: false })); passport.use(strategy); passport.serializeUser(function(user,failureRedirect: '/login' })); server = http.createServer(app).listen(51015,function(){ console.log('Express server listening on port ' + app.get('port')); });
运行测试:
var should = require('should'); var assert = require('assert'); var request = require('request'); var querystring = require('querystring'); it('Login should redirect to home and return a user token',function(done) { var postData = querystring.stringify({ username : 'user',password : 'foo' }); var options = { uri: 'http://' + '127.0.0.1' + ':' + '51015' + '/login',function(res) { console.log(res.headers); res.statusCode.should.equal(302); }) .on('data','Problem with request: ' + e.message); }); });
给出以下输出;注意包含set-cookie标头:
mocha { 'x-powered-by': 'Express','set-cookie': [ 'connect.sid=s%3ATest%20UID.NC0hY3rYGMdnN560ewpf%2FaJbO%2BNd9M7QLz3gnse0eLs; Path=/; Expires=Wed,09 Sep 2015 13:08:06 GMT; HttpOnly' ],date: 'Wed,09 Sep 2015 13:07:06 GMT',connection: 'close' } 1) Login should redirect to home and return a user token 0 passing (69ms) 1 failing 1) Login should redirect to home and return a user token: Uncaught AssertionError: Test not implemented
除了已删除的用户架构和硬编码的配置值之外,我的代码应与您的代码相同,因此我对您如何获取set-cookie标头感到茫然.
您是否正在使用可能影响会话或cookie的任何其他中间件?
[编辑2]
问题是(在您的repository中)您将会话中间件添加到与server.listen执行的范围不同的范围内,因此对应用程序所做的更改实际上不会生效.
不要让服务器在测试组之前开始监听,而是应该为每个测试启动一次,并立即将所需的所有参数传递给它.我已经向您的存储库提交了一个pull request,其中包含了我可能会如何执行此操作的详细信息,因为它不是一小部分代码,并且在此处粘贴并不是很理想.
请花点时间阅读并理解这些更改,因为我只关心会话令牌的发送,并且我不保证其他功能是否会受到这些更改的影响.