Laravel 11中Lockout事件监听器未触发问题求助
我正在开发首个Laravel项目——简易用户管理系统,使用Laravel 11.16.0(Jetstream/Livewire)+ Fortify实现登录功能。系统默认配置为1分钟内5次登录失败触发账号锁定,测试时会返回429 HTTP错误,但自定义的Lockout事件监听器未触发:监听器中的error_log日志未输出,User表的account_locked字段也未被设为true。
需求是:当用户因多次登录失败被锁定时,将User表中对应用户的account_locked(boolean类型,默认false)字段更新为true。
相关代码如下:
EventServiceProvider.php
namespace App\Providers; use Illuminate\Auth\Events\Lockout; use App\Listeners\LockoutListener; use Illuminate\Support\ServiceProvider; class EventServiceProvider extends ServiceProvider { protected $listen = [ Failed::class => [ FailedLoginListener::class, ], Lockout::class => [ LockoutListener::class, ], Authenticated::class => [ SuccessfulLoginListener::class, ], ]; }
LockoutListener.php
namespace App\Listeners; use App\Models\User; use Illuminate\Auth\Events\Lockout; class LockoutListener { public function handle(Lockout $event): void { error_log('Lockout event triggered!'); User::where('email', $event->request->user->email)->update(['account_locked' => true]); } }
问题排查与解决步骤
1. 补全EventServiceProvider的类引入
当前代码中Failed::class和Authenticated::class未引入对应命名空间,会导致事件监听注册失败,补充后代码如下:
namespace App\Providers; use Illuminate\Auth\Events\Lockout; use Illuminate\Auth\Events\Failed; use Illuminate\Auth\Events\Authenticated; use App\Listeners\LockoutListener; use App\Listeners\FailedLoginListener; use App\Listeners\SuccessfulLoginListener; use Illuminate\Support\ServiceProvider; class EventServiceProvider extends ServiceProvider { protected $listen = [ Failed::class => [ FailedLoginListener::class, ], Lockout::class => [ LockoutListener::class, ], Authenticated::class => [ SuccessfulLoginListener::class, ], ]; }
2. 修正LockoutListener中的用户查询逻辑
Lockout事件触发时用户尚未完成认证,$event->request->user为null,无法获取邮箱。应直接从请求中取登录提交的email参数:
namespace App\Listeners; use App\Models\User; use Illuminate\Auth\Events\Lockout; use Illuminate\Support\Facades\Log; class LockoutListener { public function handle(Lockout $event): void { Log::info('Lockout event triggered for email: ' . $event->request->email); User::where('email', $event->request->email)->update(['account_locked' => true]); } }
3. 清除事件缓存
Laravel 11默认开启事件缓存,修改EventServiceProvider后需执行命令清除缓存使配置生效:
php artisan event:clear
后续若需优化性能,可重新生成事件缓存:
php artisan event:cache
4. 确认日志输出位置
error_log的输出位置依赖PHP配置,改用Laravel自带日志系统(Log::info())后,日志会写入storage/logs/laravel.log,便于直接查看事件是否触发。
5. 验证Fortify锁定配置
确认config/fortify.php中已启用登录节流逻辑:
'features' => [ Features::login(), Features::resetPasswords(), // 其他功能... ],
Fortify的登录节流由ThrottlesLogins trait实现,满足条件时会自动触发Illuminate\Auth\Events\Lockout事件。
内容的提问来源于stack exchange,提问作者Matheus Caetano Rocha

