75

我使用 passport.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
    })
}));

编辑附加问题:只应建立一个连接(使用一个连接有限的 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');
        })
}));
4

7 回答 7

56

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

于 2012-04-16T14:15:34.480 回答
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());
于 2012-04-15T21:33:22.930 回答
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(参见这个库)可能是一个不错的选择(Express 很好地支持它)。

// 编辑

根据Connect 文档,如果您实现get,setdestroy方法就足够了。以下代码应该可以工作:

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)来存储会话数据。还要阅读其他实现的源代码以了解这个想法。

于 2012-04-15T17:39:53.927 回答
2

这对于有经验的节点用户来说可能是显而易见的,但它让我印象深刻:

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

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

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

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

如果您首先调用 passport.session() 它将不起作用(并且它不会警告您)。我认为问题在于序列化/反序列化用户功能和浪费时间。

于 2014-09-22T13:59:48.170 回答
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)
于 2014-03-07T18:48:07.100 回答
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
    })
}));

为我工作。

于 2015-05-28T20:20:48.880 回答
1

您需要更改用于会话的商店。当您的应用程序停止时,默认的“MemoryStore”不会继续存储会话。查看 github 上的 express-session 以了解更多关于 mongo 的其他商店。(不记得名字了)

于 2015-07-29T12:50:49.800 回答