会话过期的 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:如何从自己的事件监听器访问请求和会话类?