【问题标题】:Cannot get MongoDB Store to work with PassportJS无法让 MongoDB Store 与 PassportJS 一起使用
【发布时间】:2017-07-08 01:05:47
【问题描述】:

我是 Node.JS 和 Express 的初学者,但我已经设法创建了一个功能齐全的网络应用程序。我注意到在进入生产模式时,我将会话存储在 RAM 中。相反,我想将它们存储在 Mongo Store 中。

由于我正在使用 Passport,我想知道如何让序列化和反序列化函数与 Mongo Store 一起使用。存储会话似乎效果很好(我在数据库中看到它),但我无法获取它。

更准确地说,我想知道如何检索会话 ID 以从数据库中获取用户。

这是我的服务器代码:

var store = new MongoDBStore(
      {
        uri: process.env.MONGODB_URI,
        mongooseConnection: db,
        collection: 'mySessions'
      });

    // Catch errors 
    store.on('error', function(error) {
      throw error;
    });

app.use(session({
    secret: '****',
    resave: true,
    store: store,
    saveUninitialized: true,
    cookie: {
        maxAge: 7 * 24 * 60 * 60 * 1000}
    }));
app.use(passport.initialize());
app.use(passport.session());

passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT,
    clientSecret: process.env.GOOGLE_SECRET,
    callbackURL: process.env.CALLBACK_URL
  },
  function(accessToken, refreshToken, profile, done) {
        var user = new User();

        var profileUser = user.extractProfile(profile);

        done(null, profileUser.email); // The only info I need is the user email address

  }
));

passport.serializeUser(function(user, done) {
    console.log('Serializing user:'+user); // user returns the email address
    done(null, user); // The session is stored
});

var Sessions = db.collection('mySessions');

passport.deserializeUser(function (id, done) {

    console.log('Deserializing user:'+id); // What clearly doesn't work here, is that I'm trying to fetch a document using the email address instead of the "_id"...

    return Sessions.findOne({ user: id }, function (error, user) {
        console.log('Found :');
        console.log(user);
        return done(error, user);
    });
});

这是 Mongo 商店中的一个条目:

   {
    "_id": "10yEo3rU4Qumf2jw3346UtY0cCnRWNhc",
    "session": {
        "cookie": {
            "originalMaxAge": 604800000,
            "expires": {
                "$date": "2017-02-25T13:46:57.231Z"
            },
            "secure": null,
            "httpOnly": true,
            "domain": null,
            "path": "/",
            "sameSite": null
        },
        "passport": {
            "user": "le*****@*****.com"
        }
    },
    "expires": {
        "$date": "2017-02-25T13:46:57.231Z"
    }
}

我相信,如果我能够使反序列化功能正常工作,一切都会像以前一样工作。关于如何做到这一点的任何想法?

(编辑) 我编辑了反序列化函数来手动搜索我的会话 ID(我从 Mondo 数据库中获得了 ID),如下所示:

    passport.deserializeUser(function (id, done) {

    console.log('Deserializing user:'+id);
    return Sessions.findOne({ _id: 'faogaErvZirU2lVpo49M-Bkz7zuQwbhP' }, function (error, user) {
        console.log('Found :');
        console.log(user);
        return done(error, user.session.passport.user);
    });
});

而且 它有效。所以,除非我弄错了,否则我唯一需要弄清楚的是如何从 cookie 中获取 _id,对吧?

谢谢!

【问题讨论】:

    标签: node.js mongodb express mongoose passport.js


    【解决方案1】:

    在寻找答案几个小时后,我检查了 GitHub 上的类似项目,更准确地说,是 Passport 与存储会话的成功集成。

    我发现了我的问题:我需要存储我的用户,而不是他们的会话(Mongo Store 已经这样做了)。因此,我更改了我的 Google 策略以在数据库中创建一个新用户或检索其个人资料:

    var UserDB = db.collection('users');
    
    passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT,
    clientSecret: process.env.GOOGLE_SECRET,
    callbackURL: process.env.CALLBACK_URL,
    },
    function(token, refreshToken, profile, done) {
      process.nextTick(function() {
    
        UserDB.findOne({ 'id': profile.id }, function(err, user) {
          if (err)
            return done(err);
          if (user) {
            return done(null, user);
          } else {
    
             var newUser = {};
             newUser.id = profile.id;
             newUser.token = token;
             newUser.name = profile.displayName;
             newUser.email = profile.emails[0].value;            
             UserDB.insert({ 'id': profile.id, 'token': token, 'name': profile.displayName , 'email': profile.emails[0].value}, function (err) {
                   if (err) {
                      throw err;
                   }
                   return done(null, newUser);
            });
        }
      });
    });
    }));
    

    从那以后,我只需要在数据库中查找用户:

    passport.serializeUser(function(user, done) {
        done(null, user);
    });
    
    passport.deserializeUser(function (user, done) {
    
        return UserDB.findOne({ id: user.id }, function (error, user) {
    
            return done(error, user);
        });
    });
    

    我的错误是认为 serializeUser 和 deserializeUser 都是关于会话的,而实际上它都是关于用户配置文件的。会话由 Express-session 和 MongoDB Store 100% 管理,所以我不需要担心它们。

    【讨论】:

      猜你喜欢
      • 2014-10-31
      • 2018-01-02
      • 2016-11-14
      • 2015-02-01
      • 2019-05-10
      • 2017-11-20
      • 2011-05-24
      • 2019-05-17
      • 2018-06-02
      相关资源
      最近更新 更多