自定义Laravel Auth守卫遇RequestGuard::attempt不存在错误,求非改默认方案
问题:Laravel自定义Auth守卫调用
attempt方法报错 我在测试自定义Auth守卫时遇到如下错误:
> use \Illuminate\Support\Facades\Auth > Auth::guard("my_custom_guard") = Illuminate\Auth\RequestGuard {#5359} > Auth::guard("my_custom_guard")->attempt([]) BadMethodCallException Method Illuminate\Auth\RequestGuard::attempt does not exist.
我的config/auth.php配置如下:
'defaults' => [ 'guard' => 'api', 'passwords' => 'members', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'members', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'members', ], 'my_custom_guard' => [ 'driver' => 'my_custom_driver', ], ],
我知道设置默认守卫可解决问题,但希望能按需使用任意Auth守卫,请问除修改defaults外,还有什么方法使用自定义守卫?
2024年9月8日更新:补充代码如下:
use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; /** * Bootstrap any application services. */ public function boot(): void { Auth::viaRequest('custom-token', function (Request $request) { // 自定义认证逻辑,示例如下: // return User::where('token', (string) $request->token)->first(); }); }
解决方案
这个错误的核心原因是:你通过Auth::viaRequest注册的是请求驱动的守卫(RequestGuard),这类守卫本身就没有attempt方法——attempt是针对传统「账号密码凭证验证」场景设计的,仅session、jwt这类支持手动凭证校验的守卫会实现该方法。
按需使用自定义守卫,分两种场景处理:
1. 保留RequestGuard逻辑(基于请求自动认证)
不需要调用attempt,直接通过以下方式使用守卫:
// 获取已认证用户(RequestGuard会自动执行你定义的闭包逻辑) $user = Auth::guard('my_custom_guard')->user(); // 检查当前请求是否通过该守卫认证 if (Auth::guard('my_custom_guard')->check()) { // 已认证业务逻辑 }
2. 需要attempt方法(手动传入凭证验证)
若必须使用attempt,则需要创建自定义Guard类,而非依赖viaRequest,步骤如下:
步骤1:创建自定义Guard类
在app/Auth目录下创建MyCustomGuard.php:
<?php namespace App\Auth; use Illuminate\Auth\GuardHelpers; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Http\Request; class MyCustomGuard implements Guard { use GuardHelpers; protected $request; protected $provider; public function __construct(Request $request, UserProvider $provider) { $this->request = $request; $this->provider = $provider; } // 实现attempt方法,自定义凭证验证逻辑 public function attempt(array $credentials = [], $remember = false) { $user = $this->provider->retrieveByCredentials($credentials); if ($user && $this->provider->validateCredentials($user, $credentials)) { $this->login($user, $remember); return true; } return false; } // 实现获取用户的方法,可保留请求自动认证逻辑 public function user() { if (! is_null($this->user)) { return $this->user; } $token = $this->request->header('X-Custom-Token'); return $this->user = $this->provider->retrieveByCredentials(['token' => $token]); } // 实现凭证校验方法 public function validate(array $credentials = []) { $user = $this->provider->retrieveByCredentials($credentials); return $user && $this->provider->validateCredentials($user, $credentials); } // 实现登录方法 public function login($user, $remember = false) { $this->setUser($user); // 如需记住登录,可在此添加逻辑 } // 实现登出方法 public function logout() { $this->setUser(null); } }
步骤2:注册自定义Guard驱动
在AuthServiceProvider的boot方法中注册驱动:
use App\Auth\MyCustomGuard; use Illuminate\Support\Facades\Auth; public function boot(): void { Auth::extend('my_custom_driver', function ($app, $name, array $config) { $provider = Auth::createUserProvider($config['provider'] ?? 'members'); return new MyCustomGuard($app['request'], $provider); }); }
步骤3:更新config/auth.php配置
给自定义守卫关联用户提供者:
'my_custom_guard' => [ 'driver' => 'my_custom_driver', 'provider' => 'members', // 关联已配置的用户提供者 ],
完成后即可正常调用attempt方法:
if (Auth::guard('my_custom_guard')->attempt(['token' => $request->token])) { // 认证成功逻辑 }
内容的提问来源于stack exchange,提问作者Ellery Leung
相关产品推荐
相关产品推荐

