Laravel Auth attempting事件异常:非指定Guard触发事件
问题原因分析
你遇到的这个问题其实是对Laravel Auth事件绑定的一个常见误解——Auth::guard('admin')->attempting()并不是只给admin Guard绑定attempting事件回调。
Laravel的Auth系统里,attempting是一个全局触发的事件:只要任何Guard实例调用attempt()方法,都会触发这个事件。而你用Auth::guard('admin')->attempting()这种方式注册回调时,本质上是通过admin Guard实例调用了AuthManager的全局事件注册方法,最终这个回调会对所有Guard的attempt操作生效,所以web Guard调用attempt时也会触发你的GoogleAuthenticator逻辑。
解决方案
下面给你两种靠谱的解决方式,推荐第二种更规范的事件监听类写法:
方案一:在回调内判断当前Guard(快速修改)
直接在你现有的回调里增加Guard判断逻辑,确保只有admin Guard触发时才执行代码:
public function boot() { parent::boot(); Auth::attempting(function ($credentials, $remember, $login) { // 获取当前正在执行attempt操作的Guard名称 $currentGuard = Auth::currentGuard(); // 仅处理admin Guard的请求 if ($currentGuard === 'admin') { // 根据登录凭证获取对应的admin用户 $user = Auth::guard($currentGuard)->getProvider()->retrieveByCredentials($credentials); if ($user) { GoogleAuthenticator::onLogin($user); } } }); }
方案二:使用事件监听类(更规范,推荐)
Laravel的事件系统推荐用监听器类来处理事件逻辑,这样代码更清晰,也便于维护:
- 首先生成对应的监听器类:
php artisan make:listener HandleAdminAttempting --event=Illuminate\Auth\Events\Attempting
- 打开生成的
app/Listeners/HandleAdminAttempting.php,编写处理逻辑:
namespace App\Listeners; use Illuminate\Auth\Events\Attempting; use Illuminate\Support\Facades\Auth; class HandleAdminAttempting { public function __construct() { // 这里可以注入依赖 } public function handle(Attempting $event): void { // 只处理admin Guard触发的attempt事件 if ($event->guard === 'admin') { // 通过事件对象里的凭证获取用户 $user = Auth::guard($event->guard)->getProvider()->retrieveByCredentials($event->credentials); if ($user) { GoogleAuthenticator::onLogin($user); } } } }
- 最后在
EventServiceProvider的$listen数组中注册这个监听器:
protected $listen = [ // 其他已注册的事件... \Illuminate\Auth\Events\Attempting::class => [ \App\Listeners\HandleAdminAttempting::class, ], ];
这样修改后,只有当admin Guard执行attempt()时,才会触发GoogleAuthenticator的逻辑,web Guard的操作完全不会受到影响。
内容的提问来源于stack exchange,提问作者SexyMF
相关产品推荐
相关产品推荐

