9 советов по авторизации в Laravel

У Laravel есть отличная готовая система Auth, но, конечно, нам нужно настроить вещи здесь и там. Для некоторых из них не нужно искать внешние пакеты или писать много пользовательского кода, давайте исследуем, какие интересные способности скрываются под капотом Auth.

Совет 1. Параметры Auth:: routes()

Мы все, вероятно, знаем метод Auth::routes(), который исходит из пакета пользовательского интерфейса Laravel (до Laravel 7 он был включен в ядро).

Но знаете ли вы, что он может принимать массив параметров для включения/отключения определенных маршрутов Auth?

Начиная с Laravel 7, вот возможные параметры с их значениями по умолчанию:

Auth::routes([
    'login'    => true, 
    'logout'   => true, 
    'register' => true, 
    'reset'    => true,   // for resetting passwords
    'confirm'  => false,  // for additional password confirmations
    'verify'   => false,  // for email verification
]);

Эти параметры просто включают или отключают некоторые маршруты.

Чтобы понять, как они работают, вы можете посмотреть на файл AuthRouteMethods в Laravel UI:

return function ($options = []) {
    // Login Routes...
    if ($options['login'] ?? true) {
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
    }

    // Logout Routes...
    if ($options['logout'] ?? true) {
        $this->post('logout', 'Auth\LoginController@logout')->name('logout');
    }

    // Registration Routes...
    if ($options['register'] ?? true) {
        $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
        $this->post('register', 'Auth\RegisterController@register');
    }

    // Password Reset Routes...
    if ($options['reset'] ?? true) {
        $this->resetPassword();
    }

    // Password Confirmation Routes...
    if ($options['confirm'] ??
        class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) {
        $this->confirmPassword();
    }

    // Email Verification Routes...
    if ($options['verify'] ?? false) {
        $this->emailVerification();
    }
};

Совет 2. Laravel UI: генерация только контроллеров

Официальная документация определяет этот основной способ использования пользовательского интерфейса Laravel:

php artisan ui vue --auth

Но что делать, если вам не нужен визуальный интерфейс? Что делать, если вы создаете только проект на основе API, и у вас нет никакого интерфейса на стороне Laravel?

Вы все еще можете использовать Laravel Auth и его контроллеры. Установите пакет пользовательского интерфейса Laravel и запустите его:

php artisan ui:controllers

Он будет генерировать только app/Http/Controllers/Auth содержимое, поэтому вам не нужны файлы Blade/Vue для их использования.

Смотрите реализацию этой команды Artisan в репозитории Github.


Совет 3. Повторное подтверждение пароля для важных настроек

Вы когда-нибудь поддерживали репозиторий Github и пытались изменить его настройки доступа? Затем Github просит вас снова ввести свой пароль, просто чтобы убедиться, что это вы.

Начиная с Laravel 6.2, у нас также есть эта функция в фреймворке.

Laravel Password Confirm

Все, что вам нужно сделать, это добавить middleware password.confirm к маршруту(маршрутам), который вы хотите защитить.

Route::get('/secrets', 'SecretsController@show')->middleware('password.confirm');

Цитирую Дриса винца из официальной статьи о выпуске полнометражных игр:

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

Подтверждение пароля сохранит метку времени в сеансе пользователя, который по умолчанию длится три часа, так что пользователям не придется снова вводить свой пароль в течение этого периода.

Вы можете настроить эту продолжительность, используя новый password_timeout параметр конфигурации в файле config/auth.php 


Совет 4. Выполнить выход со всех устройств

Начиная с Laravel 5.6, у нас есть отдельный метод автоматического выхода из системы любых других устройств или браузеров, которые вошли в систему с нашей учетной записью:

Auth::logoutOtherDevices($password); 

Обычно это делается для выхода из системы других устройств, когда текущее устройство успешно вошло в систему. Чтобы сделать это, мы переопределяем метод authenticated()из призфайла нака AuthenticatesUsers.php и помещаем его в app/Http/Controllers/Auth/LoginController.php:

protected function authenticated(Request $request, $user)
{
    \Auth::logoutOtherDevices(request('password'));
}

Кроме того, не забудьте активировать middleware  AuthenticateSession в app/Http/Kernel.php файле, которое по умолчанию закомментировано:

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

Перенаправление после входа в систему/ регистрации: пользовательская логика

По умолчанию и Laravel LoginController, и RegisterController имеют одно и то же свойство:

class RegisterController extends Controller
{
    protected $redirectTo = RouteServiceProvider::HOME;

Таким образом, вы можете указать, на какой URL нужно перенаправить после успешного входа в систему/регистрации. Значение по умолчанию находится вapp/Providers/RouteServiceProvider.php:

class RouteServiceProvider extends ServiceProvider
{
    public const HOME = '/home';

Как вы можете настроить его?

Во-первых, вы можете изменить значение этого $redirectTo свойства на какую-то другую константу и, возможно, отдельно для входа и регистрации.

Но что делать, если у вас есть более сложная логика динамического редиректа, которая зависит, например, от роли пользователя?

Вы можете создать метод в контроллере Auth, вызвать его redirectTo()и указать свои условия внутри. Этот метод будет переопределять любые значения $redirectTo свойств.

См. пример:

class RegisterController extends Controller
{
    protected $redirectTo = RouteServiceProvider::HOME;

    protected function redirectTo()
    {
        if (auth()->user()->role_id == 1) {
            return '/admin';
        }
        return '/home';
    }

Совет 5. Быстрое Создание Новых Пользователей

Что делать, если вам нужно создать одного нового пользователя, а у вас нет готовой регистрационной формы?

Просто откройте Laravel Tinker в своем терминале:

php artisan tinker

Если вы не знакомы с Tinker, это инструмент командной строки для выполнения любого кода Laravel/PHP. Таким образом, вы можете легко создать пользователя, набрав эту команду и нажав Enter:

\App\User::create(['name' => 'Admin', 'email' => 'admin@admin.com', 'password' => bcrypt('somesecurepassword')]);

Но что делать, если вам нужно создать много пользователей для тестирования, например, 10, или 100, или 1000? Нет проблем, мы можем использовать factories класс, который поставляется по умолчанию с Laravel, вdatabase/factories/UserFactory.php:

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
    ];
});

Это значения по умолчанию для “поддельного” пользователя, которого мы можем создать. Для этого мы создадим файл сидера:

php artisan make:seeder UsersSeeder

Затем мы открываем этот сгенерированный файл database/seeds/UsersSeeder.php и заполняем run() метод следующим образом:

public function run()
{
    // This will create 100 users
    factory(App\User::class, 100)->create(); 
}

Чтобы запустить его, нам нужно выполнить эту команду:

php artisan db:seed --class=UsersSeeder

Вы можете прочитать больше о заполнении базы данных в официальной документации Laravel.


Совет 6. Войдите в систему с помощью электронной почты или имени пользователя

По умолчанию пользователи Laravel аутентифицируются с помощью электронной почты и пароля. Но что делать, если Ваш идентификатор не является электронной почтой? Какое-нибудь имя пользователя, например.

Вы можете легко изменить его, переопределив один метод из AuthenticatesUsers.php.

Вот значение по умолчанию:

trait AuthenticatesUsers
{
    // ... other methods 

    public function username()
    {
        return 'email';
    }

Вы можете скопировать это в свой LoginController.php и просто изменить значение:

class LoginController extends Controller
{
    use AuthenticatesUsers;

    // ... other methods

    public function username()
    {
        return 'username';
    }
}

Давайте сделаем еще один шаг вперед. Что делать, если ваши пользователи могут войти в систему с помощью электронной почты или имени пользователя? Таким образом, есть поле ввода под названием “Электронная почта/имя пользователя”, и они могут ввести одно или другое.

Давайте добавим “трюк” к тому же username()методу сверху. Мы проверяем, является ли введенная строка электронной почтой, в противном случае мы рассматриваем ее как имя пользователя. Эта проверка-функция PHP, даже не Laravel.

class LoginController extends Controller
{
    // ...

    public function username()
    {
        return filter_var(request('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
    }
}

Обратите внимание : не забывайте, что в вашей форме входа в систему вам нужно перейти input type="email"на type="text"


Совет 7. Слишком много попыток входа в систему: настройка параметров

Если вы попытаетесь войти в систему с недействительными учетными данными более пяти раз в течение одной и той же минуты, вы будете заблокированы с сообщением слишком много попыток входа в систему. Пожалуйста, повторите попытку через X секунд.

Этот блок будет активен в течение 1 минуты, и он уникален для имени пользователя/электронной почты и их IP-адреса.

Вы можете настроить эти параметры:

  • Количество допустимых попыток в течение минуты (по умолчанию пять попыток)
  • Сколько минут нужно блокировать входы в систему (по умолчанию 1 минута)

Эти два параметра находятся внутри трейта ThrottlesLogins:

trait ThrottlesLogins
{
    // ... other methods

    /**
     * Get the maximum number of attempts to allow.
     *
     * @return int
     */
    public function maxAttempts()
    {
        return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5;
    }

    /**
     * Get the number of minutes to throttle for.
     *
     * @return int
     */
    public function decayMinutes()
    {
        return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1;
    }
}

Таким образом, чтобы переопределить их, вы можете указать свойства внутри вашего LoginController:

class LoginController extends Controller
{
    protected $maxAttempts = 3;  // Default is 5
    protected $decayMinutes = 2; // Default is 1

    // ...
}

Совет 8. Регистрация: отключить автоматический вход в систему

По умолчанию вновь зарегистрированный пользователь автоматически входит в систему и перенаправляется на домашнюю страницу.

Если вы хотите отключить это и вместо этого показать какую-то страницу “успех”, не создавая автоматически сеанс пользователя, вот что вы можете сделать.

Оригинальный метод регистрации находится внутри трейта RegistersUsers:

trait RegistersUsers
{
    public function register(Request $request)
    {
        $this->validator($request->all())->validate();

        event(new Registered($user = $this->create($request->all())));

        $this->guard()->login($user);

        if ($response = $this->registered($request, $user)) {
            return $response;
        }

        return $request->wantsJson()
                    ? new Response('', 201)
                    : redirect($this->redirectPath());
    }

Таким образом, ваша цель состоит в том, чтобы переопределить его RegisterController и вернуть перенаправление на новую страницу, а не войти в систему:

class RegisterController extends Controller
{
    use RegistersUsers;

    public function register(Request $request)
    {
        $this->validator($request->all())->validate();

        event(new Registered($user = $this->create($request->all())));

        return redirect()->route('your_success_page_route_name');
    }

Совет 9. Логин: дополнительная проверка с помощью электронной почты / пароля

Что делать, если вам нужна дополнительная проверка, в дополнение к электронной почте и паролю по умолчанию? Например, вы хотите проверить, активен ли пользователь или нет.

Вы можете добавить дополнительные элементы в credentials массив, который определен в трейте AuthenticatesUsers:

trait AuthenticatesUsers
{
    // ...

    protected function credentials(Request $request)
    {
        return $request->only($this->username(), 'password');
    }

Вы просто переопределяете это LoginController и добавляете все, что хотите:

class LoginController extends Controller
{
    // ...

    protected function credentials(Request $request)
    {
        return $request->only($this->username(), 'password') + ['is_active' => 1];
    }

Обратите внимание: это интересный Быстрый совет, но я бы посоветовал вам выполнить такую дополнительную проверку в отдельном middleware, тогда вы могли бы предоставить пользователю более явное сообщение об ошибке, а не ошибку учетных данных по умолчанию.


Вот и все, это быстрые советы, но есть гораздо больше возможностей для расширения с помощью пользовательского кода и внешних пакетов. Так что следите за обновлениями, чтобы получить больше статей на эту тему!

Рейтинг
( 3 оценки, среднее 5 из 5 )
Maxyc Webber/ автор статьи
Мне 35 лет. Опыт профессиональной разработки 15 лет. Занимаюсь разработкой и поддержкой корпоративных систем автоматизации бизнеса, а также высоконагруженными проектами. Мне нравится решать нестандартные проблемы бизнеса. Имею опыт формирования команд под проект, налаживания процесса разработки, коммуникации программистов и заказчиков. Есть опыт работы с зарубежными заказчиками (ОАЭ, Польша, Германия, Швейцария).
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.