会话过期的 laravel 事件监听器,因为会话过期时没有调用注销事件监听器

Posted

技术标签:

【中文标题】会话过期的 laravel 事件监听器,因为会话过期时没有调用注销事件监听器【英文标题】:laravel event listener for session expire, as no logout event listener called on session expiry 【发布时间】:2018-11-28 13:46:44 【问题描述】:

场景很简单:我希望单个用户在给定时间仅从一台设备登录。使用 laravel 框架 5.2 版


这是我迄今为止的工作,使用事件监听器:

我在用户表中设置了一个 is_logged_in 标志,该标志在用户登录时为 ON。并基于其 ON 状态,它将拒绝来自同一用户的所有后续登录请求。

我使用登录尝试、登录和注销事件来实现:

    在登录尝试侦听器上执行以下代码。它将检查用户是否已经登录,然后在会话中设置一个记录的标志。


       $user = User::select('is_logged_in')->where('email', $event->credentials['email'])->first();
        if($user->is_logged_in == 1)
            Session::put('logged', 'Yes');
        else
            Session::put('logged', 'No');
        

    现在在登录事件中,会检查记录的会话标志,如果设置了则用户将强制注销,并维护 remember_token(注销时更改)


    if(session('logged') == "Yes")
        $previous_remember_token  = $event->user->remember_token;
        $previous_usesr_id = $event->user->id; 
        Auth::logout();
        $user = User::find($previous_usesr_id);
        $user->remember_token = $previous_remember_token;
        $user->save();
    else
        $event->user->is_logged_in = 1;
        $event->user->save();
    

    在注销时,我什至使用以下代码重置 is_logged_in 的用户数据库标志:


    if(session('logged') != "Yes") 
        $event->user->is_logged_in = 0;
        $event->user->save();
    

现在这是我面临的问题:

    当会话到期时,甚至不执行注销,我如何在会话到期时执行我的注销事件代码? laravel 中是否有 session:expire 事件监听器? 1.1 这也引出了另一个问题 laravel 是如何监控会话时间的,它保存在哪里呢? laravel 框架如何以及何时使会话过期? 我还想在用户关闭选项卡或浏览器时执行注销代码,这真的很难,但我认为可能是一些 ajax 函数在一定间隔后更新用户表列并编写一个 cron 作业来检查间隔并关闭数据库中的标志,有没有更好的方法来做到这一点,请指导?

【问题讨论】:

会话的全部意义是将Web服务器连接到当前用户,因此一旦过期,您基本上会“松散”两方之间的连接。我不确定您要实现什么,但是如果您想在浏览器上通知用户会话已过期,您可能会每隔 x 时间向某个路由发送 ajax 请求,该路由会检查用户是否已通过身份验证如果不在前端处理它。 @Vilius 可以说我想在注销事件上执行一些代码,但是当会话到期时,用户被注销,但 laravel 没有触发注销事件,这就是问题所在。如何捕获会话过期引起的注销事件? 【参考方案1】:

在 laravel 中创建您自己的会话驱动处理程序,并在处理程序的“destroy”和“gc”事件中执行您想要的代码。

您可以简单地复制默认的 DatabaseSessionHandler 代码 照亮/会话/DatabaseSessionHandler.php 并将其命名为 CustomeSessionHandler.php。

确保在 AppServiceProvider 中注册新的处理程序

public function boot()

  Session::extend('custom', function ($app) 

      $connection = $app['config']['session.connection'];
      $table = $app['config']['session.table'];
      $lifetime = $app['config']['session.lifetime'];
      $connection = $app['db']->connection($connection);
      return new CustomSessionHandler($connection, $table, $lifetime, $app);
  );

在你的 .env 或你的 config/session.php 使用新驱动

SESSION_DRIVER=自定义

【讨论】:

以上是关于会话过期的 laravel 事件监听器,因为会话过期时没有调用注销事件监听器的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.2:如何从自己的事件监听器访问请求和会话类?

Laravel 5.2:如何从自己的事件监听器访问请求和会话类?

Shiro-Session

如何在我的登录页面中禁用“Laravel 中的会话已过期”?

作者会话的 Laravel 更改重定向部分过期

即使会话过期,Laravel API 调用也会继续