如何可靠地检测到过期的Laravel会议?

发布于 2025-01-17 19:28:09 字数 1992 浏览 4 评论 0原文

我正在研究一个可以执行大量AJAX请求的Web客户端。后端用拉拉维尔(Laravel)写。如果后端引发了PHP异常,则后端将JSON响应发送给客户标头显示HTTP错误代码,其主体包含PHP异常的名称。

如果用户不活动一段时间,则HTTP会话到期。这意味着客户端传输的会话ID已被后端丢弃,因此会话ID未知。在这种情况下,我将除Laravel提供适当的PHP异常,例如SessionIdunknownsession Expecreied或任何此类内容。这将使Web客户端能够可靠地检测到这种情况并做出相应的反应。

但是,似乎Laravel的会话管理根本不在乎,是否存在会议。该请求可能会在以后失败(如果有一些不可预见的错误),如果呼叫图的某些代码在呼叫图中进一步尝试从会话中加载一个值并失败,因为该值不设置或null

步骤调试公布了以下跟踪:

1. Illuminate\Session\Middleware\StartSession::handle
2.   Illuminate\Session\Middleware\StartSession::getSession
3.     Illuminate\Session\Store::setId
4.   Illuminate\Session\Middleware\StartSession::handleStatefulRequest
5.     Illuminate\Session\Middleware\StartSession::startSession
6.       Illuminate\Session\Store::start
7.         Illuminate\Session\Store::loadSession
8.           Illuminate\Session\Store::readFromHandler
  • 在步骤2中,中间件从请求中读取声明的会话ID(例如,来自客户端发送的cookie)。
  • 在步骤3中,中间件在Store对象上设置ID,以供以后使用,但这实际上只是一个简单的设置器。这里什么都没发生。
  • 在步骤8中,“真实”魔术发生了,Store对象试图相对于先前设置的ID加载持久的会话数据。

但是,该代码看起来像

protected function readFromHandler() {
  if ($data = $this->handler->read($this->getId())) {
    $data = @unserialize($this->prepareForUnserialize($data));

    if ($data !== false && ! is_null($data) && is_array($data)) {
      return $data;
    }
  }

  return [];
}

Unerialize的任何错误都会通过@ -operator抑制。如果出现任何问题,即未进行的已返回falsenull或任何不是数组的东西,该方法默默地返回空数组[]。因此,如果会话不存在(错误情况),或者如果会话简单地为空,则无法区分会话(没有错误)(没有错误)。

请告诉我我正在犯错!如何可靠地检测后端中的不存在或过期的会话并返回A 一致错误消息?

我本来可以预期Laravel的以下行为:

  • 如果客户端未通过cookie发送会话ID,则创建新的会话并将新创建的会话ID返回给客户set-cookie。
  • 如果客户端通过cookie发送会话ID,并且会话ID存在,请继续进行。
  • 如果客户端通过cookie发送会话ID,并且会话ID不存在或无法加载,请停止进一步处理请求并返回错误响应。

I am working on a web client which does a lot of AJAX request. The backend is written in Laravel. If the backend throws a PHP exception, the backend sends a JSON response to the client whose header shows a HTTP error code and whose body includes the name of the PHP exception.

If a user has been inactive for a while, the HTTP session expires. This means that the session ID transmitted by the client has been discarded by the backend and thus the session ID is unknown. I would have excepted Laravel to throw a proper PHP exception in this case, e.g. something like SessionIdUnknown, SessionExpired or anything of that sort. This would enable the web client to reliably detect this situation and react accordingly.

However, it seems as if Laravel's session management does not care at all, whether the session exists or not. The request will potentially fail later (with some unforeseeable error), if some code further down the call graph tries to load a value from the session and fails, because the value is unset or null.

Step debugging unveiled the following trace:

1. Illuminate\Session\Middleware\StartSession::handle
2.   Illuminate\Session\Middleware\StartSession::getSession
3.     Illuminate\Session\Store::setId
4.   Illuminate\Session\Middleware\StartSession::handleStatefulRequest
5.     Illuminate\Session\Middleware\StartSession::startSession
6.       Illuminate\Session\Store::start
7.         Illuminate\Session\Store::loadSession
8.           Illuminate\Session\Store::readFromHandler
  • In step 2, the middleware reads the claimed session ID from the request (e.g. from the cookie sent by the client).
  • In step 3, the middleware sets the ID on the Store object for later use, but that is really only a simply setter; nothing else happens here.
  • In step 8 the "real" magic happens, the Store object tries to load the the persisted session data with respect to the previously set ID.

However, the code looks like that

protected function readFromHandler() {
  if ($data = $this->handler->read($this->getId())) {
    $data = @unserialize($this->prepareForUnserialize($data));

    if ($data !== false && ! is_null($data) && is_array($data)) {
      return $data;
    }
  }

  return [];
}

Any error by unserialize is suppressed via @-operator. If anything goes wrong, i.e. unserialized has returned false, null or anything which is not an array, the method silently returns the empty array []. So we cannot distinguish, if the session did not exist (error case) or if the session is simply empty because no data has previously been stored (no error).

Please tell me that I am erring! How do I reliably detect an non-existing or expired session in the backend and return a consistent error message?

I would have expected the following behavior by Laravel:

  • If the client does not sent a session ID via a cookie, then create a new session and return the newly created session ID back to client with set-cookie.
  • If the client sends a session ID via a cookie and the session ID exist, then proceed.
  • If the client sends a session ID via a cookie and the session ID does not exist or cannot be loaded, stop further processing of the request and return an error response.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文