Сброс пароля
Введение
Большинство веб-приложений предоставляют пользователям возможность сбросить забытые пароли. Вместо того чтобы заставлять вас заново реализовывать этот функционал самостоятельно для каждого создаваемого вами приложения, Laravel предлагает удобные сервисы для отправки ссылок для сброса пароля и, собственно, безопасного сброса паролей.
Хотите быстро начать? Установите один из стартовых комплектов в новое приложение Laravel. Стартовые комплекты позаботятся о построении всей вашей системы аутентификации, включая сброс забытых паролей.
Подготовка модели
Перед использованием функционала сброса пароля Laravel модель вашего приложения App\Models\User
должна использовать трейт Illuminate\Notifications\Notifiable
. Обычно этот трейт уже содержится по умолчанию в модели App\Models\User
при создании новых приложений Laravel.
Затем убедитесь, что ваша модель App\Models\User
реализует контракт Illuminate\Contracts\Auth\CanResetPassword
. Модель App\Models\User
Laravel, уже реализует этот интерфейс и использует трейт Illuminate\Auth\Passwords\CanResetPassword
, включающий методы, необходимые для реализации интерфейса.
Подготовка базы данных
Необходимо создать таблицу для сохранения токенов сброса пароля вашего приложения. Обычно это включено в миграцию базы данных Laravel по умолчанию 0001_01_01_000000_create_users_table.php
.
Конфигурирование доверенных хостов
По умолчанию Laravel будет отвечать на все запросы, которые он получает, независимо от содержимого заголовка Host
HTTP-запроса. Кроме того, значение заголовка Host
будет использоваться при генерации абсолютных URL-адресов вашего приложения во время веб-запроса.
Как правило, вам следует настроить свой веб-сервер (Nginx или Apache), так, чтобы он обслуживал запросы, соответствующие только указанному имени хоста.
Однако, если у вас нет возможности напрямую настроить свой веб-сервер и вам нужно указать Laravel, чтобы он отвечал только на определенные имена хостов, вы можете сделать это, используя метод промежуточного программного обеспечения trustHosts
в файле bootstrap/app.php
вашего приложения. Это особенно важно, когда ваше приложение предлагает функционал сброса пароля.
Чтобы узнать больше об этом методе посредника, обратитесь к документации посредника TrustHosts
.
Маршрутизация
Чтобы правильно реализовать поддержку, позволяющую пользователям сбрасывать свои пароли, нам нужно будет определить несколько маршрутов. Во-первых, нам понадобится пара маршрутов для обработки, позволяющей пользователю запрашивать ссылку для сброса пароля через свой адрес электронной почты. Во-вторых, нам понадобится пара маршрутов для обработки фактического сброса пароля при посещении пользователем ссылки для сброса пароля, отправленной ему по электронной почте, и последующего заполнения формы сброса пароля.
Запрос ссылки для сброса пароля
Форма запроса ссылки для сброса пароля
Сначала мы определим маршруты, которые необходимы для запроса ссылок для сброса пароля. Для начала мы определим маршрут, который возвращает шаблон с формой запроса ссылки для сброса пароля:
Route::get('/forgot-password', function () {
return view('auth.forgot-password');
})->middleware('guest')->name('password.request');
Шаблон, возвращаемый этим маршрутом, должен иметь форму с полем email
для указания адреса электронной почты, позволяющем пользователю запросить ссылку для сброса пароля.
Обработка отправки формы
Затем мы определим маршрут, который обрабатывает запрос на отправку формы из шаблона forgot-password
. Этот маршрут будет отвечать за проверку адреса электронной почты и отправку запроса на сброс пароля соответствующему пользователю:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
Route::post('/forgot-password', function (Request $request) {
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
return $status === Password::RESET_LINK_SENT
? back()->with(['status' => __($status)])
: back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');
Прежде чем двигаться дальше, давайте рассмотрим этот маршрут более подробно. Сначала проверяется атрибут запроса email
. Затем мы будем использовать встроенный в Laravel «брокер паролей» через фасад Password
, чтобы отправить пользователю ссылку для сброса пароля. Брокер паролей позаботится о получении пользователя по указанному полю (в данном случае по адресу электронной почты) и отправит пользователю ссылку для сброса пароля через встроенную систему уведомлений Laravel.
Метод sendResetLink
возвращает ключ «status». Этот статус может быть переведен с помощью помощников локализации Laravel, чтобы показать пользователю удобное сообщение о статусе его запроса. Перевод статуса сброса пароля определяется языковым файлом lang/{lang}/passwords.php
вашего приложения. Запись для каждого возможного значения ключа статуса находится в языковом файле passwords
.
По умолчанию скелет приложения Laravel не включает каталог
lang
. Если вы хотите настроить языковые файлы Laravel, вы можете опубликовать их с помощью командыlang:publish
Artisan.
Вам может быть интересно: как Laravel знает о том, как получить запись пользователя из базы данных вашего приложения при вызове метода sendResetLink
фасада Password
? Брокер паролей Laravel использует «поставщиков пользователей» вашей системы аутентификации для получения записей из базы данных. Поставщик пользователей, используемый брокером паролей, настраивается в массиве passwords
вашего файла конфигурации config/auth.php
. Чтобы узнать больше о создании пользовательских поставщиков служб, обратитесь к документации по аутентификации.
При выполнении сброса пароля самостоятельно, вы должны сами определять содержимое страницы и маршрутов. Если вам необходим каркас, включающий всю необходимую логику аутентификации и проверки, ознакомьтесь со стартовыми комплектами приложений Laravel.
Сброс пароля
Форма сброса пароля
Затем мы определим маршруты, необходимые для фактического сброса пароля, когда пользователь щелкает ссылку для сброса пароля, отправленную ему по электронной почте, и предоставляет новый пароль. Во-первых, давайте определим маршрут, который будет отображать форму сброса пароля, после того как пользователь щелкает ссылку сброса пароля. Этот маршрут получит параметр token
, который мы будем использовать позже для проверки запроса на сброс пароля:
Route::get('/reset-password/{token}', function (string $token) {
return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');
Экран, возвращаемый этим маршрутом, должен отображать форму, содержащую поле email
, поле password
, поле password_confirmation
и скрытое поле token
, которое должно содержать значение секретного $token
, полученного нашим маршрутом.
Обработка отправки формы
Конечно, нам нужно определить маршрут для фактической обработки отправки формы сброса пароля. Этот маршрут будет отвечать за проверку входящего запроса и обновление пароля пользователя в базе данных:
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
Route::post('/reset-password', function (Request $request) {
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:8|confirmed',
]);
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function (User $user, string $password) {
$user->forceFill([
'password' => Hash::make($password)
])->setRememberToken(Str::random(60));
$user->save();
event(new PasswordReset($user));
}
);
return $status === Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');
Прежде чем двигаться дальше, давайте рассмотрим этот маршрут более подробно. Сначала проверяются атрибуты запроса token
, email
, и password
. Далее мы будем использовать встроенный в Laravel «брокер паролей» (через фасад Password
) для проверки учетных данных запроса сброса пароля.
Если токен, адрес электронной почты и пароль, переданные брокеру паролей, действительны, будет вызвано замыкание, переданное методу reset
. В рамках этого замыкания, которое получает экземпляр пользователя и пароль в виде обычного текста из формы сброса пароля, мы можем обновить пароль пользователя в базе данных.
Метод reset
возвращает ключ «status».
Этот статус может быть переведен с помощью помощников локализации Laravel, чтобы показать пользователю удобное сообщение о статусе его запроса.
Перевод статуса сброса пароля определяется языковым файлом lang/{lang}/passwords.php
вашего приложения.
Запись для каждого возможного значения ключа статуса находится в языковом файле passwords
. Если ваше приложение не содержит каталога lang
, вы можете создать его, используя команду Artisan lang:publish
.
Прежде чем двигаться дальше, вам может быть интересно, как Laravel знает, как получить запись пользователя из базы данных вашего приложения при вызове метода reset
фасада Password
. Брокер паролей Laravel использует «поставщиков пользователей» вашей системы аутентификации для получения записей из базы данных. Поставщик пользователей, используемый брокером паролей, настраивается в массиве passwords
вашего файла конфигурации config/auth.php
. Чтобы узнать больше о создании пользовательских поставщиков служб, обратитесь к документации по аутентификации.
Удаление просроченных токенов
Токены сброса пароля с истекшим сроком действия будут по-прежнему присутствовать в вашей базе данных. Однако вы можете легко удалить эти записи, используя Artisan-команду auth:clear-resets
:
php artisan auth:clear-resets
Если вы хотите автоматизировать этот процесс, рассмотрите возможность добавления команды в планировщик вашего приложения:
use Illuminate\Support\Facades\Schedule;
Schedule::command('auth:clear-resets')->everyFifteenMinutes();
Настройка
Настройка ссылки для сброса
Вы можете изменить URL-адрес ссылки для сброса пароля, используя метод createUrlUsing
класса уведомлений ResetPassword
. Этот метод принимает замыкание, которое получает экземпляр ожидающего уведомление пользователя, а также токен ссылки для сброса пароля. Как правило, вызов этого метода осуществляется в методе boot
вашего поставщика служб App\Providers\AppServiceProvider
:
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
/**
* Запуск любых служб приложения.
*/
public function boot(): void
{
$this->registerPolicies();
ResetPassword::createUrlUsing(function (User $user, string $token) {
return 'https://example.com/reset-password?token='.$token;
});
}
Настройка уведомлений о сбросе пароля
Вы можете легко изменить класс уведомления, используемый для отправки пользователю ссылки для сброса пароля. Для начала переопределите метод sendPasswordResetNotification
в модели App\Models\User
. В этом методе вы можете отправить уведомление, используя любой класс уведомлений, созданный вами. Токен для сброса пароля – это первый аргумент, получаемый методом. Вы можете использовать этот $token
для создания URL сброса пароля по вашему усмотрению и для дальнейшей отправки уведомления пользователю:
use App\Notifications\ResetPasswordNotification;
/**
* Отправить пользователю уведомление о сбросе пароля.
*
* @param string $token
*/
public function sendPasswordResetNotification($token): void
{
$url = 'https://example.com/reset-password?token='.$token;
$this->notify(new ResetPasswordNotification($url));
}