是什么让 Express-Session 决定开始新的会话?
What Makes Express-Session Decide to Start a New Session?
我遇到了一个问题,我的代码中有一个地方(身份验证部分)在会话中放置了一些东西,而代码中的另一个地方试图访问它(我的 GraphQL API 部分)。问题是,当第二部分试图获取数据时,数据不存在。
当我登录 request.session.id
时,我可以清楚地看到核心问题:在两个请求之间,会话本身发生了变化。发生身份验证请求,并将数据放入会话 A,但是当 graphQL 代码访问 request.session
时,它获得没有数据的会话 B。
但是,这不是 "please debug my code for me" 请求。相反,我只想了解库的工作原理,以便自己进行调试。
任何人都可以解释一下 how/why express-session
决定(大概是在收到新请求时)它应该放弃旧会话并开始新会话吗?从我读过的内容来看,它可能与我的域设置有关,但我尝试过使用这些设置但没有成功,我真的只是想了解库的工作原理,特别是在决定重新使用会话或生成一个新会话。
@machineghost 多么好的问题!关于 express-session
模块的作用以及如何配置它存在很多混淆。我会尽力解释。
我认为围绕 express-sesion
的混淆源于这样一个事实,即该模块基本上只是将网络服务器的不同方面粘合到一个地方,即 req.session
,用于中间件、路由,并且可能 (在帮助下)websocket 连接来存储和访问有关发出请求的“用户”(读取会话)的临时数据。
该模块试图粘合在一起的三个方面是 http cookie、短期数据存储和通过中间件和路由传递的 javascript 对象 req
。为了阐明这是如何工作的,请考虑向使用 express-session
模块(简称 ES)的 Express 应用发出的“正常”HTTP 请求:
- Express 将请求传递给 ES。
- ES 查找它之前设置的 cookie。这是大多数报告的错误出现的地方。 ES 要求您的应用程序可以访问 cookie。反向代理、CORS 或 Fetch API 的不正确配置都可能阻止 ES 访问它试图在 HTTP 响应中设置的 cookie。如果每个在 ES 中遇到错误的人都打开调试器,在 the entry 中设置断点到 ES 中间件,并寻找
connect.id
cookie 的存在 - ES 报告的问题会少得多,IMO .注意:您可以解决对 cookie 的要求,但它充其量是 hacky。
- 如果 ES 找到 cookie,它会使用该值在应用程序在存储选项中配置的任何内容中查找会话。这可能是 Redis,或者 MongoDB,或者如果您没有指定它只是在节点进程的内存中。
- 如果 ES 没有找到 cookie,或者查找没有 return 会话,它将在
req
对象上创建一个名为 session
这只是一个空对象,即 {}
。中间件或更远的路由都可以访问它。
- ES 在
res
对象上设置一个 cookie 作为未来请求附加会话的一种方式,如上所述。
- ES 包装 req.end method with a function that will check if it should save the
req.session
object. Options like resave and saveUninitialized 将确定 ES 是否为给定请求保存会话。注意:对于 HTTP 重定向,例如302,res.end
方法直到新重定向的请求发出后才被调用。这意味着在重定向之前设置的会话数据不可用于重定向的请求。这是一个已知问题,解决方法是在使用 req.session.save
重定向之前显式保存会话
关于 websockets 的注意事项
为了让 websockets 与 ES 一起工作,在基本层面上,您必须获取附加到更改协议请求的会话,并将其附加到该用户的套接字。我写了一个简单的库作为例子here。注意:这是 5 年前创建的,更多的是作为一个话题而不是任何东西创建的,但是如果你仔细研究它是如何工作的,你就会明白这一点。
希望所有这些对您有所帮助,感谢您的发帖!
我遇到了一个问题,我的代码中有一个地方(身份验证部分)在会话中放置了一些东西,而代码中的另一个地方试图访问它(我的 GraphQL API 部分)。问题是,当第二部分试图获取数据时,数据不存在。
当我登录 request.session.id
时,我可以清楚地看到核心问题:在两个请求之间,会话本身发生了变化。发生身份验证请求,并将数据放入会话 A,但是当 graphQL 代码访问 request.session
时,它获得没有数据的会话 B。
但是,这不是 "please debug my code for me" 请求。相反,我只想了解库的工作原理,以便自己进行调试。
任何人都可以解释一下 how/why express-session
决定(大概是在收到新请求时)它应该放弃旧会话并开始新会话吗?从我读过的内容来看,它可能与我的域设置有关,但我尝试过使用这些设置但没有成功,我真的只是想了解库的工作原理,特别是在决定重新使用会话或生成一个新会话。
@machineghost 多么好的问题!关于 express-session
模块的作用以及如何配置它存在很多混淆。我会尽力解释。
我认为围绕 express-sesion
的混淆源于这样一个事实,即该模块基本上只是将网络服务器的不同方面粘合到一个地方,即 req.session
,用于中间件、路由,并且可能 (在帮助下)websocket 连接来存储和访问有关发出请求的“用户”(读取会话)的临时数据。
该模块试图粘合在一起的三个方面是 http cookie、短期数据存储和通过中间件和路由传递的 javascript 对象 req
。为了阐明这是如何工作的,请考虑向使用 express-session
模块(简称 ES)的 Express 应用发出的“正常”HTTP 请求:
- Express 将请求传递给 ES。
- ES 查找它之前设置的 cookie。这是大多数报告的错误出现的地方。 ES 要求您的应用程序可以访问 cookie。反向代理、CORS 或 Fetch API 的不正确配置都可能阻止 ES 访问它试图在 HTTP 响应中设置的 cookie。如果每个在 ES 中遇到错误的人都打开调试器,在 the entry 中设置断点到 ES 中间件,并寻找
connect.id
cookie 的存在 - ES 报告的问题会少得多,IMO .注意:您可以解决对 cookie 的要求,但它充其量是 hacky。 - 如果 ES 找到 cookie,它会使用该值在应用程序在存储选项中配置的任何内容中查找会话。这可能是 Redis,或者 MongoDB,或者如果您没有指定它只是在节点进程的内存中。
- 如果 ES 没有找到 cookie,或者查找没有 return 会话,它将在
req
对象上创建一个名为session
这只是一个空对象,即{}
。中间件或更远的路由都可以访问它。 - ES 在
res
对象上设置一个 cookie 作为未来请求附加会话的一种方式,如上所述。 - ES 包装 req.end method with a function that will check if it should save the
req.session
object. Options like resave and saveUninitialized 将确定 ES 是否为给定请求保存会话。注意:对于 HTTP 重定向,例如302,res.end
方法直到新重定向的请求发出后才被调用。这意味着在重定向之前设置的会话数据不可用于重定向的请求。这是一个已知问题,解决方法是在使用req.session.save
重定向之前显式保存会话
关于 websockets 的注意事项
为了让 websockets 与 ES 一起工作,在基本层面上,您必须获取附加到更改协议请求的会话,并将其附加到该用户的套接字。我写了一个简单的库作为例子here。注意:这是 5 年前创建的,更多的是作为一个话题而不是任何东西创建的,但是如果你仔细研究它是如何工作的,你就会明白这一点。
希望所有这些对您有所帮助,感谢您的发帖!