Js + Express.js + passport.js: 在服务器重启之间保持身份验证

我使用 passport.js 在 nodejs + Express.js 应用程序上处理 auth。我设置了一个 LocalStrategy 来接收来自 mongodb 的用户

我的问题是 当我重新启动节点服务器时,用户必须重新进行身份验证。这是一个问题,因为我正在积极地开发它,不想在每次重启时都不登录... (+ 我使用节点管理器)

下面是我的应用程序设置:

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 没有成功

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

编辑 附加问题: 只能建立一个连接(使用一个连接有限的 mongohq 免费服务)

编辑2强 > 解决方案(作为一个版本,我的声誉是低到现在回答我的问题

这是我最终找到的解决方案,使用猫鼬发起的连接

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');
})
}));
42113 次浏览

这是因为对会话使用 MemoryStore (默认) ,看看 memy.js (Connect 框架的一部分)中的代码:

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

以及 session.js (Express)中的这个片段

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

现在您应该明白,每次重启服务器都会重置 MemoryStore。为了保存数据,必须使用其他会话存储。您甚至可以编写自己的代码(应该不会太难) ,不过 Redis (参见 这个图书馆)可能是一个不错的选择(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,尽管我仍然建议使用像 Redis 这样的非永久性 Db)来存储会话数据。也可以通过阅读其他实现的源代码来获取想法。

我这样使用 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());

有一个称为 < strong > 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

我用的是猫鼬,我尝试了上面答案中的代码,但它对我不起作用。我犯了这个错误:

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)

对于有经验的节点用户来说,这一点可能是显而易见的,但它让我意识到:

您需要配置节点会话-例如。

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

初始化护照会话之前-例如。

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

如果您首先调用 passport.session () ,那么它不会工作(并且不会警告您)。我认为问题在于序列化/反序列化用户函数和浪费的时间。

我最后做了什么:

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 上的 Express-session,了解更多关于其他商店的信息,比如 mongo one。(想不起名字)