express req.session对象是如何持久化的

How is the express req.session object persisted?

本文关键字:持久化 req session 对象 express      更新时间:2024-07-03

我对学习Node和Express非常陌生,我仍在尝试用Express来理解代码流。假设我们在会话中有这样的代码。js:

app.post('/session', notLoggedIn, function(req, res) {
    User.findOne({
        username: req.body.username, 
        password: req.body.password
    }, function (err, user) {
        if (err) {
            return next(err);
        }
        if (user) {
            req.session.user = user;
            res.redirect('/users');
        } else {
            res.redirect('/session/new');
        }
    }); 
});

假设User是一个必需的mongo模式。我觉得奇怪的是会话。用户分配:

req.session.user = user;

由于req变量在重定向后将超出范围,但我们这样做显然是为了持久化用户数据,因此我要弄清楚以下哪种场景描述了正在发生的事情。要么(A)分配给req参数的参数(当调用回调时)存储在堆栈中的某个位置,要么(B)会话存储在堆栈上,并在传递给回调之前分配给新的req对象,要么(C)与B相同,但在用户字段上(似乎不太可能,可能是我自己设计的)。

有一个完整的会话数据结构,用于存储所有用户的所有会话信息(类似于全局,但它也可以在数据库中——至少在连接中是持久的)。每个客户端的会话数据都使用一个唯一的键索引到会话存储中,以获取该客户端的会话信息。

为给定的浏览器客户端建立会话的一部分是创建一个唯一的客户端密钥(通常存储在cookie中),该密钥成为全局会话对象的索引。

对于传入的http请求,支持会话的Express中间件会检查特定的客户端cookie,如果在http请求上找到了该特定的cookie,并且在全局会话对象/数据库中找到了该cookie,则它会将该会话存储的信息添加到请求对象中,供http请求处理程序稍后使用。

下面是一个典型的序列:

  1. 传入的HTTP请求
  2. 中间件检查会话cookie
  3. 如果会话cookie不存在,那么创建一个会话cookie,并在此过程中创建一个唯一的id来标识该http客户端
  4. 在持久会话存储中,初始化此新客户端的会话
  5. 如果存在会话cookie,则在会话存储中查找该客户端的会话数据,并将该数据添加到请求对象中
  6. 会话结束中间件处理
  7. 稍后,在快速处理此http请求的过程中,它将到达一个匹配的请求处理程序。该特定http客户端的会话存储中的会话数据已附加到请求对象,可供请求处理程序使用

我认为公认的答案遗漏了一个关键细节,@jpaddison3:"Express会话挂钩res.end()以查看请求何时完成,然后根据需要更新会话存储"

基本上,当您添加表达式会话中间件时,它会包装res.end(),以便在流关闭之前保存新的会话信息。