在 Laravel 9 中,我尝试使用自定义防护来访问登录 API
client
,我收到以下错误。请帮忙。
BadMethodCallException: Method Laravel\Passport\Guards\TokenGuard::attempt does not exist.
配置/Auth.php
'guards' => [
...
'client' => [
'driver' => 'passport',
'provider' => 'client',
],
],
'providers' => [
...
'client' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
],
错误行:
if(!$authGuard->attempt($login)){
api/AuthController.php
public function login(Request $request){
$login = $request->validate([
'email' => 'required|string',
'password' => 'required|string',
]);
try {
$authGuard = Auth::guard('client');
if(!$authGuard->attempt($login)){
$data = 'Invalid Login Credentials';
$code = 401;
} else {
$user = $authGuard->user();
$token = $user->createToken('user')->accessToken;
$code = 200;
$data = [
'user' => $user,
'token' => $token,
];
}
} catch (Exception $e) {
$data = ['error' => $e->getMessage()];
}
return response()->json($data, $code);
}
模型/Client.php
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
class Client extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
我认为
Auth::attempt()
与护照不兼容。
所以,你可以使用
Auth::check()
方法来代替。
attempt() 仅适用于实现 StatefulGuard 接口的守卫。
所以我同意约翰的观点,即尝试与 Passport 不兼容。
你可以尝试一下,它应该可以工作:
auth()->guard('client')->setUser($login);
或 Auth::guard('client')->setUser($login);
我通过将
passport
中的驱动程序从
session
更改为
config/auth.php
解决了这个问题
'clients' => [
'driver' => 'session',
'provider' => 'clients',
],
我不确定这是正确的解决方案,但它有效。
如果有更好的解决方案请随时发布答案
谢谢
Laravel Passport 似乎不支持这种类型的身份验证样式,我为解决这个问题所做的有点奇怪,但它有效。 我为所有用户模型类型创建了一个端点,如下所示:
Route::post('auth/{user_type}/login', [AuthController::class, 'login']);
然后我添加了一个辅助函数来获取我希望进行身份验证的用户模型:
function resolve_user_type(string $user_type)
{
return match ($user_type) {
'user'=> User::class,
'admin'=> Admin::class,
default => throw new InvalidArgumentException()
};
}
然后我修改了你的登录方法:
public function login(Request $request , $user_type)
{
$model = resolve_user_type($user_type);
$login = $request->validate([
'email' => 'required|email',
'password' => 'required|string',
]);
try {
$user = $model::whereEmail($login['email'])->first();
if (!$user || !Hash::check($login['password'], $user->password)) {
$data = 'Invalid Login Credentials';
$code = 401;
} else {
$token = $user->createToken('authToken', [$user_type])->accessToken;
$code = 200;
$data = [
'user' => $user,
'token' => $token,
];
}
} catch (Exception $e) {
$data = ['error' => $e->getMessage()];
}
return response()->json($data, $code);
}
其中方法 createToken() 中的第二个参数是我为用户令牌创建的范围的名称,并在启动方法的 AuthServiceProvider 文件中定义它:
Passport::tokensCan([
'user'=>'user',
'admin'=>'admin'
]);
这对于我来说足够动态,可以使用并继续前进,但请记住这三个必须相同: