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

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, тогда вы могли бы предоставить пользователю более явное сообщение об ошибке, а не ошибку учетных данных по умолчанию.


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

admin

admin

Добавить комментарий

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

%d такие блоггеры, как: