我有一个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 \应用程序,调用 /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php 在第612行并定义
如果我覆盖我的CustomUserProvider的构造函数并更改AuthServiceProvider中闭包中的params,我会收到以下错误:
参数1传递给Illuminate \ Foundation \ Application :: bootProvider() 必须是Illuminate \ Support \ ServiceProvider的实例,实例 App \ Providers \ IberoUserProvider给出,调用 /var/www/public/iberorides/vendor/laravel/framework/src/Illuminate/Foundation/Application.php 在第771行并定义
这让我觉得我没有以正确的方式做事。
有人能让我朝着正确的方向前进吗?
非常感谢你。
答案 0 :(得分:4)
解决方案很简单。
首先,尽管其他教程说过,但您不必在配置提供程序中注册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')
。
答案 1 :(得分:2)
我找到的所有解决方案都不适合我,所以我想出了一个非常简单的方法。 ( 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));
您甚至可以根据某些条件等在登录控制器中设置提供程序。
答案 2 :(得分:0)
可以通过AuthServiceProvider的启动方法中的以下代码来对EloquentUserProvider进行非常小的自定义。
Auth::provider('eloquent', function($app, array $config)
{
return new class($app['hash'], $config['model']) extends \Illuminate\Auth\EloquentUserProvider
{
};
});
答案 3 :(得分:0)
如果这对寻求自定义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 实现中,还需要自定义其他位置,以便将我的特定用例付诸实践(加上密码重置表单本身)。采用这种方法时,每种情况都会有所不同。但这可能会为您指明有用的方向,具体取决于您的特定要求。