如何在 Laravel 5.4 中添加自定义用户提供程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45024429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add a custom User Provider in Laravel 5.4
提问by Hugo A
I have a Laravel 5.4 app, in which I have to authenticate my admin users from an external API, which when successfully logged in it returns a JSON with user information.
我有一个 Laravel 5.4 应用程序,其中我必须从外部 API 验证我的管理员用户,当成功登录时,它返回一个包含用户信息的 JSON。
I am creating a custom guard to make this:
我正在创建一个自定义守卫来做到这一点:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users'
],
'custom' => [
'driver' => 'session',
'provider' => 'customusers'
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
and this is my custom provider:
这是我的自定义提供程序:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'customusers' => [
'driver' => 'jsonresponse',
'model' => App\Admin::class,
]
],
After that, I am not sure how to continue. I've read some tutorials like the one from George Buckingham, and I have created a custom User provider (Right now I just need it to extend from EloquentUserProvider, eventually I will override some functions to connect to the API)
在那之后,我不确定如何继续。我已经阅读了一些教程,比如George Buckingham 的教程,并且我创建了一个自定义用户提供程序(现在我只需要它从 EloquentUserProvider 扩展,最终我将覆盖一些函数以连接到 API)
<?php
namespace App\Providers;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\Str;
class CustomUserProvider extends EloquentUserProvider {
}
then registered it both in App\Providers\AuthServiceProvider
然后在 App\Providers\AuthServiceProvider 中注册它
public function boot()
{
$this->registerPolicies();
Auth::provider('jsonresponse', function($app, array $config) {
return new CustomUserProvider($app['hash'], $config['model']);
});
}
and in config/app.php
并在 config/app.php
'providers' => [
// Lots of other providers
// Own providers
App\Providers\CustomUserProvider::class,
],
But after that, I get the following error:
但在那之后,我收到以下错误:
Argument 1 passed to Illuminate\Auth\EloquentUserProvider::__construct() must be an instance of Illuminate\Contracts\Hashing\Hasher, instance of Illuminate\Foundation\Application given, called in /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php on line 612 and defined
传递给 Illuminate\Auth\EloquentUserProvider::__construct() 的参数 1 必须是 Illuminate\Contracts\Hashing\Hasher 的实例,给定的 Illuminate\Foundation\Application 实例,在 /var/www/public/iberorides/vendor/laravel 中调用/framework/src/Illuminate/Foundation/Application.php 在第 612 行并定义
If I override the constructor of my CustomUserProvider and change the params in the closure in AuthServiceProvider, I get the following error:
如果我覆盖 CustomUserProvider 的构造函数并更改 AuthServiceProvider 中闭包中的参数,则会出现以下错误:
Argument 1 passed to Illuminate\Foundation\Application::bootProvider() must be an instance of Illuminate\Support\ServiceProvider, instance of App\Providers\IberoUserProvider given, called in /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php on line 771 and defined
传递给 Illuminate\Foundation\Application::bootProvider() 的参数 1 必须是 Illuminate\Support\ServiceProvider 的实例,给出的 App\Providers\IberoUserProvider 的实例,在 /var/www/public/iberorides/vendor/laravel/framework 中调用/src/Illuminate/Foundation/Application.php 在第 771 行并定义
This makes me think I am not doing things the right way.
这让我觉得我没有以正确的方式做事。
Could someone put me in the right direction?
有人能把我放在正确的方向吗?
Thank you so much.
非常感谢。
采纳答案by Hugo A
The solution was simple.
解决办法很简单。
First, despite what other tutorials said, you do not have to register the CustomUserProvider
in your config providers (Laravel 5.4 here). This was the cause of the errors I was getting.
首先,不管其他教程怎么说,你不必CustomUserProvider
在你的配置提供程序中注册(这里是 Laravel 5.4)。这是我得到错误的原因。
I only had to override two methods from EloquentUserProvider
, retrieveByCredentials(array $credentials)
where you return a model based on the credentials provided, and validateCredentials(UserContract $user, array $credentials)
where you return a boolean depending in wheter credentials are correct.
我只需要覆盖来自 的两个方法EloquentUserProvider
,retrieveByCredentials(array $credentials)
根据提供的凭据返回模型,以及validateCredentials(UserContract $user, array $credentials)
根据凭据是否正确返回布尔值。
You can use this same custom provider class with many providers, not just one, e.g.
您可以将相同的自定义提供程序类与许多提供程序一起使用,而不仅仅是一个,例如
'providers' => [
'customusers' => [
'driver' => 'jsonresponse',
'model' => App\User::class,
],
'customadmins' => [
'driver' => 'jsonresponse',
'model' => App\Admin::class,
],
],
After that, when you need to check auth with any provider, yo need to provide the provider as guard e.g. Auth::guard('customusers')
.
之后,当您需要向任何提供者检查身份验证时,您需要提供提供者作为保护,例如Auth::guard('customusers')
。
回答by Mark Baaijens
Very small customizations of the EloquentUserProvider can be done by means of the following code inside the boot method of your AuthServiceProvider.
可以通过 AuthServiceProvider 的 boot 方法中的以下代码对 EloquentUserProvider 进行非常小的自定义。
Auth::provider('eloquent', function($app, array $config)
{
return new class($app['hash'], $config['model']) extends \Illuminate\Auth\EloquentUserProvider
{
};
});
回答by Mārti?? Briedis
None of the solutions I found quite worked for me, so I figured out a super easy way. (Laravel 5.4)
我发现的所有解决方案都不适合我,所以我想出了一个超级简单的方法。( Laravel 5.4)
My problem was that I had to allow users to log in with their phone number too.
我的问题是我也必须允许用户使用他们的电话号码登录。
I override the EloquentUserProvider
:
我覆盖了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();
}
}
And in my AppServiceProvider
boot methode I added these lines:
在我的AppServiceProvider
引导方法中,我添加了以下几行:
Auth::setProvider(new PhoneUserProvider(app(Hasher::class), UserModel::class));
Auth::setProvider(new PhoneUserProvider(app(Hasher::class), UserModel::class));
You can even set provider in login controller, based on some conditions, etc.
您甚至可以根据某些条件等在登录控制器中设置提供程序。
回答by NVV
In case it is of any help to others looking for a way to customize the retrieveByCredentials
method, it is possible to do so without implementing a custom UserProvider. The EloquentUserProvidersimply takes a credentials array and builds out a Userquery using where clauses for each key/value pair in the array. So if you already have a class that is defining those credentials, you can simply customize there.
如果它对其他人寻求自定义retrieveByCredentials
方法有任何帮助,则可以在不实现自定义UserProvider 的情况下这样做。所述EloquentUserProvider简单地取一个凭证阵列,并建立了一个用户使用查询,其中用于阵列中的每个键/值对的条款。因此,如果您已经有一个定义这些凭据的类,您可以简单地在那里进行自定义。
In my case, I had a ResetPasswordControllerthat implemented ResetsPasswords. I was looking to modify how the user was selected during submission (using an id and password, rather than email and password), so I overrode the credentials
method, replacing emailwith ID_Contactlike so:
就我而言,我有一个ResetPasswordController是实现ResetsPasswords。我想修改提交期间选择用户的方式(使用 ID 和密码,而不是电子邮件和密码),所以我覆盖了该credentials
方法,用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'
);
}
There were additional places that needed to be customized within the ResetsPasswordsimplementation in order to bring my particular use case into practice (plus the password reset form itself). Each scenario would be a little different when taking this approach. But this may point some in a helpful direction, depending on your particular requirements.
为了将我的特定用例付诸实践(加上密码重置表单本身),还需要在ResetsPasswords实现中自定义其他地方。采用这种方法时,每种情况都会有所不同。但这可能会指出一些有用的方向,具体取决于您的特定要求。
回答by Evol Rof
as @Mark Baaijens say
正如@Mark Baaijens 所说
In your AuthServiceProvider
在你的 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();
}
};
});
}