1

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

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

这是我所做的

所以我尝试的第一件事是使用这样的req.session.reload()方法:

更新快速会话会话

在 Node.js 和 express-session 中更改和刷新会话数据

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

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

使用 session_id 从 Mongo 快速加载会话

所以作为最后的手段,我使用 MongoClient 直接获取会话数据并使用获得的数据更新会话。我对路由处理程序使用异步并等待 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;
  }
}

这是我检查过的其他答案

这个只更新过期,所以我假设它对我不起作用,我确实将 resave 设置为 false 以便它不会尝试保存每个请求,因为它保存到数据库我认为它无关通过更新,我尝试将其设置为 true,但什么也没发生。

更新/刷新快速会话

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

如何在请求之外以快递方式访问会话?

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

4

1 回答 1

0

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

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

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

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

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

于 2021-05-12T19:42:59.440 回答