Node.js + express.js + passport.js:在服务器重启之间保持身份validation

我使用passport.js来处理我的nodejs + express.js应用程序的身份validation。 我设置了一个LocalStrategy从MongoDB中取用户

我的问题是, 当我重新启动节点服务器时用户必须重新进行身份validation 。 这是一个问题,因为我正在积极开发它,不要在每次重新启动时都要login…(+我使用节点监督器)

这是我的应用程序设置:

app.configure(function(){ app.use('/static', express.static(__dirname + '/static')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(express.session({secret:'something'})); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); }); 

和会话序列化设置:

 passport.serializeUser(function(user, done) { done(null, user.email); }); passport.deserializeUser(function(email, done) { User.findOne({email:email}, function(err, user) { done(err, user); }); }); 

我尝试了使用connect-mongodb没有成功的博客上给出的解决scheme(删除链接,因为它不存在了)

 app.use(express.session({ secret:'something else', cookie: {maxAge: 60000 * 60 * 24 * 30}, // 30 days store: MongoDBStore({ db: mongoose.connection.db }) })); 

编辑额外的问题:只应该build立一个连接(使用一个连接有限的mongohq免费服务)

编辑2解决scheme(作为我的名声是我现在低回答我的问题

这是我终于find的解决scheme,使用mongoose启动连接

 app.use(express.session({ secret:'awesome unicorns', maxAge: new Date(Date.now() + 3600000), store: new MongoStore( {db:mongoose.connection.db}, function(err){ console.log(err || 'connect-mongodb setup ok'); }) })); 

有一个名为connect-mongo的开源,它完全符合你的需求 – 在mongodb中保存会话数据

使用示例(重新使用mongoose打开的连接):

 var session = require('express-session'); var MongoStore = require('connect-mongo')(session); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/sess'); app.use(express.session({ secret:'secret', maxAge: new Date(Date.now() + 3600000), store: new MongoStore( // Following lines of code doesn't work // with the connect-mongo version 1.2.1(2016-06-20). // {db:mongoose.connection.db}, // function(err){ // console.log(err || 'connect-mongodb setup ok'); // } {mongooseConnection:mongoose.connection} ) })); 

你可以阅读更多关于它在这里: https : //github.com/kcbanner/connect-mongo

我使用connect-mongo:

 var MongoStore = require('connect-mongo'); var sess_conf = { db: { db: mydb, host: localhost, collection: 'usersessions' // optional, default: sessions }, secret: 'ioudrhgowiehgio' }; app.use(express.session({ secret: sess_conf.secret, maxAge: new Date(Date.now() + 3600000), store: new MongoStore(sess_conf.db) })); [...] // Initialize Passport! Also use passport.session() middleware, to support // persistent login sessions (recommended). app.use(passport.initialize()); app.use(passport.session()); 

这是因为您使用MemoryStore(默认)会话。 从memory.js(Connect框架的一部分)看这个代码:

 var MemoryStore = module.exports = function MemoryStore() { this.sessions = {}; }; 

和这个从session.js(快速)

 function session(options){ /* some code */ , store = options.store || new MemoryStore /* some code */ } 

现在你应该明白,每一次服务器重启都会重置MemoryStore。 为了保持数据,你必须使用其他会话存储。 你甚至可以写你自己的(不应该太难),尽pipeRedis(看这个库 )可能是一个不错的select(Express也很好的支持)。

//编辑

根据Connect文档 ,如果你实现getsetdestroy方法,这对你来说已经足够了。 下面的代码应该可以工作:

 customStore = { get : function(sid, callback) { // custom code, for example calling MongoDb }, set : function(sid, session, callback) { // custom code }, destroy : function(sid, callback) { // custom code } } app.use(express.session({ store: customStore })); 

你只需要实现调用MongoDb(或任何其他的Db,尽pipe我仍然推荐使用Redis之类的nonpermament)来存储会话数据。 另外阅读其他实现的源代码来获取这个想法。

对于有经验的节点用户来说这可能很明显,

您需要configuration节点会话 – 例如

 app.use(session({secret: "this_is_secret", store: ...})); 

初始化护照会话之前 – 例如

 app.use(passport.initialize()); app.use(passport.session()); 

如果你先调用passport.session(),它将不起作用(它不会警告你)。 我认为这个问题是由于序列化/反序列化的用户function和浪费时间。

我正在使用mongoose,我尝试了上面的答案中提供的代码,并没有为我工作。 我遇到这个错误时:

 Error: db object already connecting, open cannot be called multiple times 

但是,这对我有用:

 app.use(express.session({ secret:'secret', maxAge: new Date(Date.now() + 3600000), store: new MongoStore({mongoose_connection:mongoose.connection}) })) 

注意:如果您因为某种原因没有使用MongoStore,则需要执行以下操作:

 npm install connect-mongo --save 

然后:

 var MongoStore = require('connect-mongo')(express) 

我最终做了什么:

 var expressSession = require('express-session'); var redisClient = require('redis').createClient(); var RedisStore = require('connect-redis')(expressSession); ... app.use(expressSession({ resave: true, saveUninitialized: true, key: config.session.key, secret: config.session.secret, store: new RedisStore({ client: redisClient, host: config.db.host, port: config.db.port, prefix: 'my-app_', disableTTL: true }) })); 

为我工作。

您需要更改您在会话中使用的商店。 应用程序停止时,默认的“MemoryStore”不会继续存储会话。 在github上查看快速会话,了解更多关于其他商店的信息,例如mongo。 (不记得名字)