是什么让 Express-Session 决定开始新的会话?

mac*_*ost 1 javascript session express express-session

我遇到了一个问题,我的代码中的一个地方(身份验证部分)在会话中放置了一些东西,而代码中的另一个地方试图访问它(我的 GraphQL API 部分)。问题是,当第二部分试图获取数据时,它并不存在。

当我登录时,request.session.id我可以清楚地看到核心问题:在两个请求之间,会话本身发生了变化。身份验证请求发生,并将数据放入会话 A,但是当 graphQL 代码访问时,request.session它获取会话 B,但没有数据。

但是,这不是“请为我调试我的代码”请求。相反,我只想了解该库的工作原理,以便我可以自行调试。

任何人都可以解释一下如何/为什么express-session决定(大概是在获得新请求时)它应该放弃旧会话并开始一个新会话吗?从我读过的内容来看,它可能与我的域设置有关,但我尝试使用那些没有成功的方法,实际上我只是想了解该库的工作原理,特别是在决定重新使用会话或生成一个新的。

jwa*_*ags 6

@machineghost 真是个好问题!关于express-session模块的功能以及如何配置它存在很多混淆。我会尽力解释。

我认为围绕express-sesion这一点的混乱源于这样一个事实,即该模块基本上只是将网络服务器的不同方面粘合到一个地方,即req.session,用于中间件、路由和潜在的(在帮助下)websocket 连接来存储和访问有关“用户”的临时数据"(阅读会话)提出请求的人。

该模块试图粘合在一起的三个方面是 http cookie、短期数据存储以及req通过中间件和路由传递的 javascript 对象。为了阐明这是如何工作的,请考虑一个“正常”的 HTTP 请求,该请求已提供给使用该express-session模块(简称 ES)的 Express 应用程序:

  • Express 将请求传递给 ES。
  • ES 查找它之前设置的 cookie。这是大多数报告的错误出现的地方。ES 要求您的应用程序可以访问 cookie。反向代理、CORS 或 Fetch API 的错误配置都可能会阻止 ES 访问它尝试在 HTTP 响应中设置的 cookie。如果在 ES 中遇到错误的每个人都打开一个调试器,在 ES 中间件的入口设置一个断点,并寻找connect.idcookie的存在- ES 报告的问题会少得多,IMO。注意:您可以解决对 cookie 的要求,但充其量是 hacky。
  • 如果 ES 找到 cookie,它会使用该值在应用程序在 store 选项中配置的任何内容中查找会话。这可能是 Redis 或 MongoDB,或者如果您没有指定它只是在节点进程的内存中。
  • 如果 ES 没有找到 cookie,或者如果查找没有返回会话,它将在被req调用的对象上创建一个属性,该属性session只是一个空对象,即{}. 中间件或线路更远的路线都可以访问它。
  • res如上所述,ES 在对象上设置 cookie作为未来请求附加会话的一种方式。
  • ES用一个函数包装req.end方法,该函数将检查它是否应该保存req.session对象。类似的选项重新保存saveUninitialized将确定是否ES给定请求保存会话。注意:在 HTTP 重定向的情况下,例如 302,该res.end方法直到新重定向的请求发出后才会被调用。这意味着在重定向之前设置的会话数据对重定向的请求不可用。这是一个已知问题,解决方法是在重定向之前显式保存会话req.session.save

关于 websocket 的注意事项

为了让 websocket 与 ES 一起工作,在基本层面上,您必须获取附加到请求的会话以更改协议并将其附加到该用户的套接字。我在这里写了一个简单的库作为例子。注意:这已经 5 年了,它更多地是作为一个话题而不是任何东西来创建的,但是如果你仔细看看它是如何工作的,你就会明白这个想法。

我希望所有这些都有帮助,感谢发布!