如何使用 connect mongo 更新请求之外的快速会话?

How to update express session outside of the request with connect mongo?

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

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

中获取过时的数据

这是我所做的

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

Updating express-session sessions

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

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

Express load Session from Mongo with session_id

所以不得已我使用MongoClient直接获取session数据,并用获取的数据更新session。我对路由处理程序使用异步并等待 MongoClient 获取数据。它不等待 await 而是一直抛出 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;
  }
}

这是我检查过的其他答案

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

Renewing/Refreshing Express Session

并且在此它使用了 socket.io 和 store.get() 所以它也不会起作用。

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

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

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

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

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

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

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

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

这不完全是 good/efficient 的方式...在到达路线之前 运行 需要做很多事情,所以我认为这会降低性能...但这就是我让它工作的方式,如果有人能想出更好的主意,我将不胜感激