2012-04-15 83 views
66

我使用passport.js来处理我的nodejs + express.js应用程序的身份验证。我设置了LocalStrategy从MongoDB获取用户Node.js + express.js + passport.js:在服务器重启之间保持身份验证

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

这里是我的应用程序设置:

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); 
    }); 
}); 

我试图解决在博客上给定的(删除,因为它不存在任何更多的链接)使用连接-的MongoDB没有成功

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

编辑另一个问题:只有一个连接应(使用一个联接有限mongohq免费服务)

EDIT 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'); 
     }) 
})); 
+0

只是FYI:博客链接重定向到一个模仿约会网站......不知道它是否是好的了。 – anthonylawson 2013-03-12 15:13:56

+1

噢,我删除了链接。 – 2013-03-15 10:38:41

+11

开发人员使scuzzy约会网站。 – 2013-06-30 19:07:07

回答

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

Arnaud,谢谢,我有同样的问题。你能更清楚地了解db:mongoose.connection.db吗?我不确定这意味着什么。 – 2012-05-01 17:20:36

+0

对于迟到的反应,我很抱歉,我从墨西哥回到法国,我会在48小时后更加有效。回应:你必须在通过mongoose初始化之后将mongo连接实例传递给connect-mongodb。 mongoose.connection.db是我们正在讨论的实例,我们通过“db”属性将它传递给connectdb。 – 2012-05-03 16:21:13

+0

你在#github上有一个工作示例吗? – 2014-04-09 16:07:36

5

这是因为你用MemoryStore的(默认)的会话。看看这个代码memory.js(连接框架的一部分):

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

和session.js(快递)这个片段

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

现在你应该明白,每一个服务器启动复位MemoryStore的。为了保留数据,你必须使用其他会话存储。你甚至可以编写你自己的(不应该太难),尽管Redis(见this library)可能是一个不错的选择(Express也支持它)。

//编辑

根据the Connect documentation如果实现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(或任何其他数据库虽然我还是建议使用nonpermament一个类似的Redis),用于存储会话数据。还请阅读其他实现的源代码以获取该想法。

+1

谢谢。正如你所看到的,我尝试过使用connect-mongodb(和connect-mongo)而没有成功,会话不会保存在我的数据库中。 – 2012-04-15 20:58:13

+1

@ArnaudRinquin对不起,不知何故,我没有看到。 :)我已经更新了答案。我并不熟悉connect-mongodb和connect-mongo(我将Redis作为会话存储使用猫鼬),所以我唯一给你的建议是:尝试自己实现会话存储。 – freakish 2012-04-15 21:40:15

+0

感谢您的帮助,但几分钟前我找到了解决方案,并看到您的回复,因为我想发布解决方案。 – 2012-04-15 22:00:57

6

我使用连接蒙戈像这样:

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()); 
+0

谢谢,但我有一个额外的问题:我只需要一个连接在我的数据库上,因为我使用了mongohq免费服务(仅限一个连接)。 – 2012-04-15 22:02:42

+0

好的,这里是使用connect-mongodb和重新使用猫鼬连接的最终的,干净的解决方案 – 2012-04-16 14:14:20

1

我正在使用猫鼬,我试了上面的答案中提供的代码,它并没有为我工作。

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) 
2

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

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

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

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

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

如果你先调用passport.session(),它将不起作用(它不会警告你)。我认为问题出在序列化/反序列化用户函数,浪费了几个小时。

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 
    }) 
})); 

为我工作。

1

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