【问题标题】:How to create a Custom Auth Guard / Provider for Laravel 5.7如何为 Laravel 5.7 创建自定义 Auth Guard / Provider
【发布时间】:2019-02-15 10:04:21
【问题描述】:

我正在从 Laravel 4 迁移到 5.7,但我的自定义身份验证提供程序遇到了问题。我遵循了各种演练(例如123)以及相当多的谷歌搜索。

我已尝试通过以下方式使其正常工作:

设置守卫和提供者并链接到我的目标模型。


    'defaults' => [
        'guard' => 'custom_auth_guard',
        'passwords' => 'users',
    ],

    'guards' => [

        'custom_auth_guard' => [
            'driver' => 'session',
            'provider' => 'custom_auth_provider',
        ],
    ],

    'providers' => [

        'custom_auth_provider' => [
            'driver' => 'custom',
            'model' => App\UserAccount::class,
        ],        
    ],

注册上述提供程序中定义的驱动程序。为方便起见,我正在搭载 AuthServiceProvider


...
    public function boot()
    {
        $this->registerPolicies();

        \Auth::provider('custom',function() {            
        return new App\Auth\CustomUserProvider;
        });
    }
...

创建了我的自定义提供程序,其中包含我的retrieveByCredentials 等。我已将逻辑替换为一些 die() 以验证它是否在此处生成。在 Laravel 4 中,它曾经转到 validateCredentials()。


class CustomUserProvider implements UserProviderInterface {

    public function __construct()
    {
        die('__construct');
    }

    public function retrieveByID($identifier)
    {   
        die('retrieveByID');
    }

    public function retrieveByCredentials(array $credentials)
    {
        die('retrieveByCredentials');
        }

    public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
    { 
        die('validateCredentials');
        }

作为参考,App/UserAccount 看起来像这样

class UserAccount extends Authenticatable
{
    use Notifiable;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'public.user_account';

    // no updated_at, created_at
    public $timestamps = false;

    private $_roles = [];
    private $_permissions = [];
}

最后,我通过我的控制器调用它。

        if(\Auth::attempt($credentials){
            return \Redirect::intended('/dashboard');
        }

我也试过直接打电话给守卫

        if(\Auth::guard('custom_auth_guard')->attempt($credentials){
            return \Redirect::intended('/dashboard');
        }

这会导致以下错误:"Auth guard [custom_auth_guard] is not defined."

我已经尝试了一些其他命令来确保没有缓存问题:

composer update
php artisan cache:clear

结果:当我调用 Auth::attempt($credentials) Laravel 试图在 users 表上运行查询。预期的结果是它会命中 CustomUserProvider 中的 die() 之一……或者至少尝试查询模型中定义的 public.user_account。

我已经搞砸了一段时间,我一定错过了一些简单的东西......希望对 Laravel 5 有更多经验的人可以看到我做错了什么。

提前致谢!!

【问题讨论】:

    标签: laravel


    【解决方案1】:

    设法解决了。几个小问题,但主要的一个是我试图捎带 AuthServiceProvider 而不是我自己的提供者。以下是我在 Laravel 5.7 中为自定义身份验证提供程序所做的工作

    在 config.auth.php 中设置提供者。

    'providers' => [
    
        'user' => [
            'driver' => 'eloquent',
            'model' => \UserAccount::class,
        ],        
    ],
    

    在 app/providers/ 中创建一个新的提供者。这会将上面列出的提供商与正确的用户提供商代码相关联。

    namespace App\Providers;
    
    use Auth;
    use App\Auth\CustomUserProvider;
    use Illuminate\Support\ServiceProvider;
    
    class CustomAuthProvider extends ServiceProvider
    {
    
        public function register()
        {
            //
        }
    
        public function boot()
        {
            Auth::provider('eloquent',function()
            {
                return new CustomUserProvider(new \UserAccount());
            });
        }
    }
    

    在 app/auth/ 中创建了我的自定义提供程序。这是验证用户的逻辑,并替换了 auth 的 laravel 函数。我在这里遇到了一个问题,它正在验证但没有填充用户对象。我最初有一个测试来查看对象是否为空,如果是,则填充......但是它总是填充有一个空对象。删除测试允许我调用 Auth::user() 函数。

    namespace App\Auth;
    
    use Illuminate\Contracts\Auth\Authenticatable as UserContract;
    use Illuminate\Auth\EloquentUserProvider;
    
    class CustomUserProvider implements EloquentUserProvider{
    
        public function __construct()
        {
            $this->user = $user;
        }
    
        public function retrieveByID($identifier)
        {   
            $this->user = \UserAccount::find($identifier);
            return $this->user;
        }
    
        public function retrieveByCredentials(array $credentials)
        {
           // find user by username
            $user = \UserAccount::where('name', $credentials['username'])->first();
    
            // validate
            return $user;
        }
    
        public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
        { 
            //logic to validate user
        }
    

    更新后的 App/Models/UserAccount 看起来像这样

    use Illuminate\Foundation\Auth\User as Authenticatable;
    class UserAccount extends Authenticatable
    {
        protected $table = 'public.user_account';
    
        // no updated_at, created_at
        public $timestamps = false;
    
        private $_roles = [];
        private $_permissions = [];
    }
    

    就是这样。我现在可以通过以下调用进行验证

            if(\Auth::attempt($credentials){
                return \Redirect::intended('/dashboard');
            }
    

    【讨论】:

    • 您的提供程序代码对我有所帮助,但是,由于我是从 API 进行身份验证,所以我无法实现 validateCredentialsretrieveByCredentials 等方法,因此我没有任何我项目中的数据库,所有东西都在 API 的数据库中,根据 Laravel 文档,我需要返回 Authenticatable 的实现,但我不打算创建任何模型。希望我可以返回任何类型的数据...
    猜你喜欢
    • 2016-06-10
    • 2020-04-22
    • 2016-03-11
    • 1970-01-01
    • 2016-09-07
    • 2021-10-28
    • 2017-07-29
    • 2017-09-24
    • 2016-07-30
    相关资源
    最近更新 更多