У Laravel есть отличная готовая система Auth, но, конечно, нам нужно настроить вещи здесь и там. Для некоторых из них не нужно искать внешние пакеты или писать много пользовательского кода, давайте исследуем, какие интересные способности скрываются под капотом Auth.
- Совет 1. Параметры Auth:: routes()
- Совет 2. Laravel UI: генерация только контроллеров
- Совет 3. Повторное подтверждение пароля для важных настроек
- Совет 4. Выполнить выход со всех устройств
- Перенаправление после входа в систему/ регистрации: пользовательская логика
- Совет 5. Быстрое Создание Новых Пользователей
- Совет 6. Войдите в систему с помощью электронной почты или имени пользователя
- Совет 7. Слишком много попыток входа в систему: настройка параметров
- Совет 8. Регистрация: отключить автоматический вход в систему
- Совет 9. Логин: дополнительная проверка с помощью электронной почты / пароля
Совет 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, у нас также есть эта функция в фреймворке.
Все, что вам нужно сделать, это добавить 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, тогда вы могли бы предоставить пользователю более явное сообщение об ошибке, а не ошибку учетных данных по умолчанию.
Вот и все, это быстрые советы, но есть гораздо больше возможностей для расширения с помощью пользовательского кода и внешних пакетов. Так что следите за обновлениями, чтобы получить больше статей на эту тему!