如何在 Laravel 5.4 中添加自定义用户提供程序
Posted
技术标签:
【中文标题】如何在 Laravel 5.4 中添加自定义用户提供程序【英文标题】:How to add a custom User Provider in Laravel 5.4 【发布时间】:2017-12-14 22:03:16 【问题描述】:我有一个 Laravel 5.4 应用程序,我必须从外部 API 对我的管理员用户进行身份验证,当成功登录时,它会返回一个带有用户信息的 JSON。
我正在创建一个自定义守卫来做到这一点:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users'
],
'custom' => [
'driver' => 'session',
'provider' => 'customusers'
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
这是我的自定义提供者:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'customusers' => [
'driver' => 'jsonresponse',
'model' => App\Admin::class,
]
],
在那之后,我不知道如何继续。我已经阅读了一些类似the one from George Buckingham 的教程,并且我创建了一个自定义用户提供程序(现在我只需要它从 EloquentUserProvider 扩展,最终我将重写一些函数来连接到 API)
<?php
namespace App\Providers;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\Str;
class CustomUserProvider extends EloquentUserProvider
然后在 App\Providers\AuthServiceProvider 中注册它
public function boot()
$this->registerPolicies();
Auth::provider('jsonresponse', function($app, array $config)
return new CustomUserProvider($app['hash'], $config['model']);
);
在 config/app.php 中
'providers' => [
// Lots of other providers
// Own providers
App\Providers\CustomUserProvider::class,
],
但在那之后,我收到以下错误:
参数 1 传递给 Illuminate\Auth\EloquentUserProvider::__construct() 必须是 Illuminate\Contracts\Hashing\Hasher 的实例, Illuminate\Foundation\Application 给定,调用 /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php 在第 612 行并定义
如果我重写我的 CustomUserProvider 的构造函数并更改 AuthServiceProvider 中的闭包中的参数,我会收到以下错误:
参数 1 传递给 Illuminate\Foundation\Application::bootProvider() 必须是 Illuminate\Support\ServiceProvider 的实例, App\Providers\IberoUserProvider 给定,调用 /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php 在第 771 行并定义
这让我觉得我做事的方式不对。
有人能把我引向正确的方向吗?
非常感谢。
【问题讨论】:
【参考方案1】:解决方案很简单。
首先,不管其他教程怎么说,您不必在配置提供程序中注册CustomUserProvider
(此处为 Laravel 5.4)。这就是我遇到错误的原因。
我只需要覆盖 EloquentUserProvider
中的两个方法,retrieveByCredentials(array $credentials)
将根据提供的凭据返回模型,validateCredentials(UserContract $user, array $credentials)
根据凭据是否正确返回布尔值。
您可以将同一个自定义提供程序类与许多提供程序一起使用,而不仅仅是一个,例如
'providers' => [
'customusers' => [
'driver' => 'jsonresponse',
'model' => App\User::class,
],
'customadmins' => [
'driver' => 'jsonresponse',
'model' => App\Admin::class,
],
],
之后,当您需要检查任何提供者的身份验证时,您需要提供提供者作为保护,例如Auth::guard('customusers')
.
【讨论】:
谢谢!我尝试为您的解决方案中的类似问题创建分步答案:***.com/a/46224576/2056125 嘿!我真的是新构建 laravel 应用程序,我正在处理类似的场景,但我对如何在这些方法中覆盖“retrieveByCredentials”和“validateCredentials”感到困惑,我是否应该对身份验证路由进行 API 调用并从 API 的 Json 响应构建用户模型?提前致谢! @JuniorSilva 乐于助人。你为什么不问这个问题,这样我就可以在那里回答? @Bul Ikana,我刚刚问了一个问题,如果你能帮我,我会很高兴的!提前致谢!【参考方案2】:正如@Mark Baaijens 所说
在你的AuthServiceProvider
public function boot()
$this->registerPolicies();
Auth::provider('eloquent', function($app, array $config)
return new class ($app['hash'], $config['model']) extends EloquentUserProvider
public function retrieveById($identifier)
$model = $this->createModel();
$condition = [$model->getAuthIdentifierName() => $identifier];
if ($model instanceof User)
$condition['custom_more_filed'] = 1;
return $model->newQuery()
->where($condition)
->first();
;
);
【讨论】:
【参考方案3】:如果它对寻找自定义retrieveByCredentials
方法的其他人有任何帮助,可以在不实现自定义UserProvider 的情况下这样做。 EloquentUserProvider 只需要一个凭证数组,并使用数组中每个键/值对的 where 子句构建一个 User 查询。因此,如果您已经有一个定义这些凭据的类,您可以简单地在那里进行自定义。
就我而言,我有一个实现 ResetsPasswords 的 ResetPasswordController。我希望修改在提交期间如何选择用户(使用 ID 和密码,而不是电子邮件和密码),所以我覆盖了 credentials
方法,将 email 替换为 ID_Contact 像这样:
/**
* Get the password reset credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(Request $request)
return $request->only(
'password',
'password_confirmation',
'token',
'ID_Contact'
);
ResetsPasswords 实现中还有其他地方需要自定义,以便将我的特定用例付诸实践(加上密码重置表单本身)。采用这种方法时,每种情况都会有所不同。但这可能会指出一些有用的方向,具体取决于您的特定要求。
【讨论】:
【参考方案4】:可以通过 AuthServiceProvider 的 boot 方法中的以下代码对 EloquentUserProvider 进行非常小的自定义。
Auth::provider('eloquent', function($app, array $config)
return new class($app['hash'], $config['model']) extends \Illuminate\Auth\EloquentUserProvider
;
);
【讨论】:
【参考方案5】:我发现没有一个解决方案对我很有效,所以我想出了一个超级简单的方法。 (Laravel 5.4)
我的问题是我必须允许用户也使用他们的电话号码登录。
我覆盖了EloquentUserProvider
:
class PhoneUserProvider extends EloquentUserProvider
public function retrieveByCredentials(array $credentials)
if (!$credentials)
return null;
// Fallback to original email authorization
if (filter_var($credentials['email'], FILTER_VALIDATE_EMAIL))
return parent::retrieveByCredentials($credentials);
// Assume we are logging in with a phone number
return UserModel::where('phone', $credentials['email'])->first();
在我的AppServiceProvider
引导方法中,我添加了以下几行:
Auth::setProvider(new PhoneUserProvider(app(Hasher::class), UserModel::class));
您甚至可以根据某些条件等在登录控制器中设置提供程序。
【讨论】:
您能否提供指向“要点”或“博客文章”的链接,说明如何正确使用这种方法。 没有更多内容了。你被困在哪里了? 1. 创建一个扩展 EloquentUserProvier 的自定义类 2. 通过调用 Auth::setProvider.. 注册您的用户提供程序以用作身份验证提供程序以上是关于如何在 Laravel 5.4 中添加自定义用户提供程序的主要内容,如果未能解决你的问题,请参考以下文章
无法在工匠自定义命令 Laravel 5.4 中获取模型关系