PAYATHON 2026

express-session 如何检测 req.session 的属性变更?

数据小陈

结论

express-session 会在请求开始时加载会话并挂到 req.session 上,也会安排在响应结束时检查会话状态。因此,即使它注册在路由之前,后续代码对同一会话对象所做的修改也能被检查到。

它如何发现变更

请求处理过程大致如下:

  1. express-session 读取当前会话,创建或恢复会话对象,并设置 req.session。
  2. 后续中间件和路由处理器读取或修改这个对象。
  3. 响应结束时,express-session 将会话当前状态与加载时记录的状态进行比较。
  4. 如果发现需要保存的变更,就调用 session store 保存会话。没有变更时,是否还要进行其他处理,例如更新过期时间,则取决于会话配置和 store 的能力。

它不需要拦截每次属性赋值。常见实现会在加载会话时记录状态摘要,并在响应结束时重新计算后进行比较。因此,增加或更新 req.session 上的字段这类普通修改也会被发现。

示例

app.use(session(sessionOptions));

app.get('/visit', (req, res) => {
  req.session.visits = (req.session.visits || 0) + 1;
  res.send(`Visits: ${req.session.visits}`);
});

处理 /visit 时,路由修改的是已经挂在 req 上的会话对象。res.send() 结束响应后,express-session 会检查该对象,并在适用时将更新写入 store。

配置和使用注意

saveUninitialized、resave 以及 store 是否支持 touch 等配置,会影响未修改的会话是否保存、已有会话是否重新保存,以及如何更新会话过期时间。这些配置不会改变中间件按注册顺序运行的规则。

如果需要在响应结束前确认会话已保存,可以调用 req.session.save(callback) 显式请求保存。这适用于需要在后续操作前确认保存完成的场景。具体行为取决于所用的 session store 及其实现。

备注:内容仅供参考。