【问题标题】:How to update express session outside of the request with connect mongo?如何使用 connect mongo 在请求之外更新快速会话?
【发布时间】:2021-05-28 09:11:20
【问题描述】:

我正在构建与 Express Session 的集成,并尝试在单独的 webhook 中对用户进行身份验证。所以我需要一种方法来更新请求之外的用户会话,因为这将是一个不同的请求。

我所做的是将会话 ID 传递给新请求,并使用 MongoClient 更新数据库中的会话。我记得 Express Session 只将 ID 存储在客户端,而数据存储在数据库中,所以我假设更新数据库就可以了。但情况似乎并非如此。我可以清楚地看到 MongoDB 上的会话已全部更新,但我一直在 req.session.data 中获取过时的数据。

这就是我所做的

所以我尝试的第一件事是使用req.session.reload() 方法,如下所示:

Updating express-session sessions

change and refresh session data in Node.js and express-session

但它仍然给我过时的数据,好像该函数什么也没做(它确实打印了日志,所以我认为它确实运行了)。

我尝试使用这个使用 Express Session 中的 store.get() 方法,但它给了我 undefined 会话。

Express load Session from Mongo with session_id

所以作为最后的手段,我使用 MongoClient 直接获取会话数据并使用获得的数据更新会话。我对路由处理程序使用异步并等待 MongoClient 获取数据。它不会等待等待,而是继续抛出undefined。我认为这是我的代码错误,但我能够使用代码获取用户数据,它确实等待 MongoClient 获取数据,但不知何故它不适用于会话数据。

这是我的部分代码:

app.router.get('/login', async function (req, res, next) {
  req.session.auth = await mongo.getCookie(req.session.id).auth;
  req.session.user = await mongo.getCookie(req.session.id).user;
  console.log('Login Action', req.session.id, req.session.auth, req.session.user);
}
module.exports.getCookie = async function getCookie(identifier) {
  try {
    let database = client.db('database');
    let collection = await database.collection('sessions');
    let result = await collection.findOne({ _id: identifier }, function(err, res) {
      if (err) throw err;
      return res;
    });
    return result;
  }
  catch (err) {
    console.error(err);
    return null;
  }
}

这是我检查过的其他答案

这个只更新过期时间,所以我认为它对我不起作用,我确实将 resave 设置为 false,这样它就不会尝试保存每个请求,因为它保存到我认为它有的数据库与更新无关,我尝试将其设置为 true,但没有任何反应。

Renewing/Refreshing Express Session

在这方面它使用了 socket.io 和 store.get(),所以它不能正常工作。

How to access session in express, outside of the req?

有人可以指导我如何让 Express Session 从数据库中更新,或者有没有办法从数据库中获取数据并以这种方式更新会话?

【问题讨论】:

    标签: node.js mongodb express-session connect-mongo


    【解决方案1】:

    所以我最终想通了,结果会话没有从数据库更新。看起来它在缓存中有一个本地副本,但我的印象是快速会话只使用数据库。

    我知道我的数据确实在数据库中,但不在缓存中或存储快速会话的本地副本的任何地方。所以解决这个问题的最简单方法是用数据库上的数据更新本地副本。

    我创建了这个函数来更新会话数据

    async function sessionUpdate(req) {
      try {
        // get the data on the database
        let tempSession = await mongo.getCookie(req.session.id);
    
        // if the data exist, we can copy that to our current session
        if (tempSession) {
          req.session.auth = tempSession.auth;
          req.session.user = tempSession.user;
          
          // you can do other stuff that you need to do with the data too
          if (req.session.health == null || req.session.health == undefined || typeof req.session.health === 'undefined') {
            req.session.health = 0;
          }
    
          // This update and save the data to the session
          req.session.save( function(err) {
            req.session.reload( function (err) {
              //console.log('Session Updated');
            });
          });
        }
        else if (!tempSession) {
          req.session.auth = false;
          req.session.user = null;
          req.session.ip = request.connection.remoteAddress;
        }
      }
      catch (err) {
        console.error(err);
      }
    }
    

    现在我们有了一个可以更新会话数据的函数,我们需要在任何地方实现它。我使用中间件来做到这一点,你也可以使用其他方法,但这必须在路由或会话逻辑之前调用。

    // middleware with no mounted path so it is used for all requests
    receiver.router.use(async function (req, res, next) {
      try {
        await sessionUpdate(req);
      }
      catch (err) {
        console.error(err);
      }
      next();
    });
    

    这并不是一种很好/有效的方法......甚至在到达路线之前就需要运行很多东西,所以我认为它会使性能下降一点......但这就是我的方式让它发挥作用,如果有人能想出更好的主意,我将不胜感激?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 2017-10-11
      • 2020-07-13
      • 2018-02-12
      • 2013-02-23
      • 2011-09-17
      相关资源
      最近更新 更多