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

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

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

  1. Для начала нужно создать свой Provider, который наследуется от EloquentUserProvider и переопределяем в нем метод retrieveByCredentials:
    <?php
    namespace App\Extensions;
    use Illuminate\Support\Str;
    use Illuminate\Auth\EloquentUserProvider;
    class CustomUserProvider extends EloquentUserProvider
    {
        /**
         * Retrieve a user by the given credentials.
         *
         * @param  array $credentials
         * @return \Illuminate\Contracts\Auth\Authenticatable|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' => App\Entities\User::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  \Illuminate\Http\Request $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        $data = $request->only($this->username(), 'password');
        $data['role'] = $this->accessRole; //приватная переменная, указывалась для каждого модуля отдельно
        return $data;
    }
        

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

Комментарии (0)


  1. Комментариев пока нет.