Node.js + express.js + passport.js:在服务器重新启动之间保持身份验证


75

我使用password.js在我的nodejs + express.js应用程序上处理身份验证。我设置了一个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
    })
}));

编辑其他问题:仅应建立一个连接(使用一项connexion有限的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');
        })
}));

仅供参考:该博客链接将我重定向到一个模糊的约会网站...不知道它是否再有用。
anthonylawson

1
哦,好的,我删除了链接。
Arnaud Rinquin

12
开发人员制作混乱的约会网站。
Jim Schubert

我有一个相反的问题。重新启动浏览器后,要求用户重新进行身份验证。你有这个问题吗?
sasha.sochka,2015年

1
可能 是RTFM:github.com/expressjs/session >默认情况下cookie.maxAge为null,这意味着未设置“ expires”参数,因此cookie成为浏览器会话cookie。当用户关闭浏览器时,cookie(和会话)将被删除。
Arnaud Rinquin 2015年

Answers:


55

有一个名为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更加明确?我不确定这是什么意思。
雅克·塔迪

抱歉,我的回复很晚,我要从墨西哥返回法国,我们将在48小时内为您服务。响应:好,您必须在mongoose初始化mongo连接实例后将其传递给connect-mongodb。mongoose.connection.db是我们正在讨论的实例,我们通过“ db”属性将其传递给connectdb。
Arnaud Rinquin

注意,这是一个旧代码,需要适应新API的方式。
Arnaud Rinquin 2014年

4
{db:mongoose.connection.db} 不起作用。您可以使用{mongooseConnection:mongoose.connection}实际起作用的方法
lmaooooo,2015年

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

谢谢,但是我还有一个问题:使用mongohq免费服务时,我只希望数据库上有一个连接(仅一个连接)。
Arnaud Rinquin 2012年

好了,这是使用connect-mongodb和重用猫鼬连接的最终清洁解决方案
Arnaud Rinquin 2012年

5

这是因为您将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。为了保留数据,您必须使用其他会话存储。您甚至可以编写自己的(应该不会太困难),尽管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,尽管我仍然建议使用Redim这样的非永久性数据库)来存储会话数据。另请阅读其他实现的源代码以了解这一想法。


1
谢谢。如您所见,我尝试使用connect-mongodb(和connect-mongo)未成功,但会话未保存在数据库中。
Arnaud Rinquin 2012年

1
@ArnaudRinquin抱歉,我不知何故。:)我已经更新了答案。我对connect-mongodb和connect-mongo都不熟悉(我在将Redis作为会话存储使用Mongoose),所以我为您提供的唯一建议是:尝试自己实现会话存储。
奇异的

感谢您的帮助,但几分钟前我就找到了解决方案,并在我想发布解决方案时看到了您的回复。
Arnaud Rinquin 2012年

1
@ArnaudRinquin您知道您可以回答自己的问题并将其标记为已接受吗?因为说实话,我的回答无济于事。:)
怪异的2012年

我知道,但是我的声誉太低了。我会尽快做。谢谢你的诚实。
Arnaud Rinquin 2012年

2

对于经验丰富的节点用户来说,这可能是显而易见的,但它吸引了我:

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

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

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

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

如果您首先调用passport.session(),它将无法正常工作(并且不会发出警告)。我认为问题出在序列化/反序列化用户功能和浪费时间上。


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)

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上查看express-session,以了解更多有关mongo的其他商店。(不记得名字了)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.