【问题标题】:Laravel's Session Handler does not invoke it's destroy functionsLaravel 的 Session Handler 不会调用它的销毁函数
【发布时间】:2021-03-23 21:00:10
【问题描述】:

我正在尝试在用户会话到期时添加其他功能。在 Session Handler 丢弃之前,我需要来自用户会话的数据(它在中间件之前被丢弃并且不可用)。

我在 Laravel 的原生 Illuminate\Session\FileSessionHandler.php 中添加了日志,但是 destroy() 或 gc() 函数都不会在会话到期时触发。

FileSessionHandler 仅添加了日志:

namespace Illuminate\Session;
...
class FileSessionHandler implements SessionHandlerInterface
{ 
  ...

  public function __construct(Filesystem $files, $path, $minutes)
  {
    Log::debug('within FileSessionHandler __construct()');
    ...
  }

  public function open($savePath, $sessionName) {
    Log::debug('within FileSessionHandler open()');
    ...
  }

  public function close() {
    Log::debug('within FileSessionHandler close()');
    ...
  }

  public function read($sessionId) {
    Log::debug('within FileSessionHandler read()');
    ...
  }

  public function write($sessionId, $data) {
    Log::debug('within FileSessionHandler write()');
    ...
  }

  public function destroy($sessionId) {
    Log::debug('within FileSessionHandler destroy()');
    ...
  }

  public function gc($lifetime) {
    Log::debug('within FileSessionHandler gc()');
    ...
  }
}

laravel.log 会话到期后刷新:

[2021-03-23 20:51:30] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:51:30] stage.DEBUG: within FileSessionHandler write()  
[2021-03-23 20:51:36] stage.DEBUG: within FileSessionHandler construct()  
[2021-03-23 20:51:36] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:51:36] stage.DEBUG: within FileSessionHandler write()  
[2021-03-23 20:51:36] stage.DEBUG: within FileSessionHandler construct()  
[2021-03-23 20:51:36] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:51:37] stage.DEBUG: within FileSessionHandler write()  
[2021-03-23 20:51:37] stage.DEBUG: within FileSessionHandler construct()  
[2021-03-23 20:51:37] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:51:38] stage.DEBUG: within FileSessionHandler write()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler construct()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler write()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler construct()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler read()  
[2021-03-23 20:52:54] stage.DEBUG: within FileSessionHandler write()  

config\session.php:

'driver' => 'file',
...
'lifetime' => env('SESSION_LIFETIME', 120),

有谁知道为什么destroy() 和gc() 从未被触发,或者会话实际上在哪里被丢弃?

【问题讨论】:

  • 你如何控制会话过期?
  • @apokryfos 我把它设置在config\session.php:'driver' => 'file', ... 'lifetime' => env('SESSION_LIFETIME', 120),
  • 尝试将'lottery' => [1, 1] 设置为应该在每个请求结束时触发gc。我认为destroy 只能通过例如手动触发。 session()->regenerate(true).
  • @apokryfos 做到了,现在gc() 正在被触发!但是,它会触发您提到的每个请求。我想要一个仅在用户会话到期时触发的函数,以删除表中的某些记录。你知道解决方案吗?我唯一能想到的就是将内置的lifetime 设置为无限,然后从中间件完成所有操作,将时间附加到会话中的时间戳以模仿内置的空闲功能(在最后一次请求的 X 时间后过期) .
  • 我认为你需要找到一种不同的方法来解决这个问题,比如在表中的记录上添加一个“有效直到”时间戳,并在每个用户请求时扩展它。问题是用户的会话将在用户不活动 X 时间后过期,因此当调用 gc 时,会调用它来清理其他用户的过期会话,而不是刚刚有活动的当前用户的会话

标签: php laravel session


【解决方案1】:

从@apokryfos 提供的发现来看,Session Handler 不是为当前用户设计的,而是为其他用户的清理而设计的。

为了根据用户的会话到期执行数据库修改,可能有:

  • 一个 CRON 作业/提供程序,用于根据记录的时间戳执行数据库修改
  • 在您需要的会话数据为 仍然可用(在会话处理程序删除会话之前)。

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    相关资源
    最近更新 更多