My blog

Делаем авторизацию немного сложнее на Laravel 5.3

Иногда случается такое, что при авторизации необходимо проверить данные из реляционных таблиц, или добавить условие, которое фреймворком не предусмотрено.

Единственный для себя выход я нашел в создании своего драйвера для авторизации, начнем все по порядку:

  1. Для начала нужно создать свой Provider, который наследуется от EloquentUserProvider и переопределяем в нем метод retrieveByCredentials:
    <?php
    namespace AppExtensions;
    use IlluminateSupportStr;
    use IlluminateAuthEloquentUserProvider;
    class CustomUserProvider extends EloquentUserProvider
    {
        /**
         * Retrieve a user by the given credentials.
         *
         * @param  array $credentials
         * @return IlluminateContractsAuthAuthenticatable|null
         */
        public function retrieveByCredentials(array $credentials)
        {
            if (empty($credentials)) {
                return;
            }
            // First we will add each credential element to the query as a where clause.
            // Then we can execute the query and, if we found a user, return it in a
            // Eloquent User "model" that will be utilized by the Guard instances.
            $query = $this->createModel()->newQuery();
            foreach ($credentials as $key => $value) {
                if (!Str::contains($key, ['password', 'role'])) {
                    $query->where($key, $value);
                }
                if (Str::contains($key, 'role')) {
                    $query->whereHas('roles', function ($query) use ($value) {
                        $query->where('slug', 'like', $value . '%');
                    });
                }
            }
            return $query->first();
        }
    }
        
  2. Теперь скажем фреймворку что работа с пользователями будет происходить через наш новый провайдер. Для этого изменим пару строк в config/auth.php:
    'users' => [
        'driver' => 'custom',
        'model' => AppEntitiesUser::class //Обратите внимание на путь к модели, у меня он не стандартный
    ],
        
  3. Но прежде чем проверять необходимо объявить провайдер. Для этого указываем в AuthServiceProvider в методе boot следующее:
    Auth::provider('custom', function ($app, array $config) {
        return new CustomUserProvider($app['hash'], $config['model']);
    });
        
  4. Теперь можно проверить авторизацию, она будет работать через новый провайдер, но осталась ещё одна мелочь. Если посмотреть на код в пункте первом, видно что у меня в метод передаются данные с ключами role,password и стандартным полем email.
    Чтобы добавить в массив $credentials данные необходимо в контроллере LoginController.php переопределить метод credentials, в моем случае это выглядело так:
    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  IlluminateHttpRequest $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        $data = $request->only($this->username(), 'password');
        $data['role'] = $this->accessRole; //приватная переменная, указывалась для каждого модуля отдельно
        return $data;
    }
        

Теперь авторизация готова и полностью работает. Вам необходимо будет только заменить выборку на свою в методе retrieveByCredentials в 1 пункте.

3 года назад Laravel Laravel, Авторизация 0