我使用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 解决方案(作为版本,我的名声很低,现在回答我的问题
这是我最终找到的解决方案,使用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');
})
}));
答案 0 :(得分:54)
有一个名为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
答案 1 :(得分:6)
我像这样使用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());
答案 2 :(得分:5)
这是因为您使用MemoryStore(默认)进行会话。从memory.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(请参阅this library)可能是一个不错的选择(并且Express得到了很好的支持)。
//编辑
根据the Connect documentation,如果您实施get
,set
和destroy
方法,就足够了。以下代码应该有效:
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这样的nonpermament)来存储会话数据。另请阅读其他实现的源代码以获取想法。
答案 3 :(得分:2)
这对于有经验的节点用户来说可能是显而易见的,但它让我感到震惊:
您需要配置节点会话 - 例如
app.use(session({secret: "this_is_secret", store: ...}));
在 初始化护照会话之前- 例如
app.use(passport.initialize());
app.use(passport.session());
如果你首先打电话给passport.session()它将无法工作(它不会警告你)。我认为问题在于序列化/反序列化用户函数和浪费的时间。
答案 4 :(得分:1)
我正在使用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)
答案 5 :(得分:1)
我最终做了什么:
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
})
}));
适合我。
答案 6 :(得分:1)
您需要更改用于会话的商店。当应用程序停止时,默认的“MemoryStore”不会继续存储会话。查看github上的快速会话,了解更多关于mongo one等其他商店的信息。 (不记得名字)