Как в Laravel сделать принудительную смену пароля каждые 30 дней.
Доброго времени суток. В одном из проектов на Laravel понадобилось заставить пользователя менять свой пароль каждые 30 дней. Я использовал стандартную аутентификацию Laravel. Увы из коробки такого функционала нет. Но добавить его очень просто. И так, приступим.
Разобьём нашу задачу на несколько шагов:
- Редактируем таблицу users и меняем модель User
- Создадим страницу изменения пароля
- Создание middleware
- Настройка из конфигурационного файла
Шаг 1. Редактируем таблицу users и меняем модель User
Создаем новую миграцию, которая добавит поле “password_change_at” в таблицу users. Для этого используем команду в консоли:
php artisan make:migration add_column_password_change_at_table_users –table=users
Открываем только что созданную миграцию и добавляем в метод up следующий код:
Schema :: table ('users', function (Blueprint $ table) { $table->timestamp('password_changed_at')->nullable(); });
А в метод down:
Schema::table('users', function (Blueprint $table) { $table->dropColumn('password_changed_at'); });
Запускаем миграцию:
php artisan migrate
Ок. С таблицей мы разобрались. Теперь немного отредактируем модель User. Добавим разрешение на массовое заполнение нашего поля. Для этого изменим свойство:
protected $fillable = [ 'name', 'email', 'password', ];
Следующим образом:
protected $fillable = [ 'name', 'email', 'password', ' password_changed_at ', ];
Вот и все. Переходим к следующему шагу.
Шаг 2. Создание страницы изменения пароля.
Я подразумеваю, что авторизация у вас настроена. Если нет, то обратитесь к документации по Laravel. Или прочитайте у меня на блоге «Авторизация в Laravel 5.3 из нескольких таблиц», но тут немножко другая тема.
Давайте добавим в routes/web.php еще один роут:
Route::get('password/expired', 'Auth\ExpiredPasswordController@expired') ->name('password.expired');
Дальше создадим контроллер, используя команду artisan
php artisan make:controller Auth/ExpiredPasswordController
Теперь перейдем в только, что созданный контроллер и добавим метод:
public function expired() { return view('auth.passwords.expired'); }
Который будет вызывать вьюшку с формой ввода нового пароля. Что-то типа такого:
Отлично при нажатии на кнопку «Сохранить» наша форма будет отправлена POST запросом на ‘password/expired’. Отлично, давайте создадим еще один роут:
Route::post('password/expired', 'Auth\ExpiredPasswordController@postExpired') ->name('password.postExpired');
И в контроллер ExpiredPasswordController добавим метод:
public function postExpired(PasswordExpiredRequest $request) { if (!Hash::check($request->current_password, $request->user()->password)) { return redirect()->back()->withErrors(['current_password' => 'Не верный текущий пароль']); } $request->user()->update([ 'password' => bcrypt($request->password), 'password_changed_at' => Carbon::now()->toDateTimeString() ]); return redirect()->back()->with(['status' => 'Пароль изменен']); }
Давайте рассмотрим, что делает этот метод:
- Мы получаем данные, которые прошли валидацию Form Request (). В нашем случае это класс PasswordExpiredRequest, который мы создадим чуть ниже.
- Мы проверяем текущий пароль введенный в форме $request->current_password с хешем пароля хранящимся в базе $request->user()->password
- Обновляем пароль пользователя $request->user()->update
- Возвращаемся обратно с сообщением, что пароль изменен.
Теперь давайте создадим новый класс PasswordExpiredRequest, который будет наследоваться от FormRequest. Для этого в консоле введите команду:
php artisan make:request PasswordExpiredRequest
Откройте только, что созданный файл и измените в методе authorize
public function authorize() { return true; }
Теперь измените метод rules
public function rules() { return [ 'current_password' => 'required', 'password' => 'required|confirmed|min:6', ]; }
Ну вот и все.
Шаг 3. Создание Middleware для проверки истекшего пароля.
Для создания Middleware используйте команду
php artisan make: middleware PasswordExpired
Теперь откройте только, что созданный middleware. И после namespace App\Http\Middleware добавьте:
use Carbon\Carbon;
Carbon – это библиотека для работы с датами. Более подробно о ней вы можете прочитать в моей статье «Работа с датой и временем в Laravel и PHP с помощью Carbon».
В измените метод handle:
public function handle($request, Closure $next) { $user = $request->user(); $password_changed_at = new Carbon(($user->password_changed_at) ? $user->password_changed_at : $user->created_at); if (Carbon::now()->diffInDays($password_changed_at) >= 30) { return redirect()->route('password.expired'); } return $next($request); }
Тут мы проверяем дату хранящуюся в поле password_change_at с текущей датой и если разница больше или равна 30 дней, то нас редиректит на форму с изменением пароля.
Теперь нужно зарегистрировать наш Middleware в app/Http/Kernel.php Добавим в свойство protected $routeMiddleware
protected $routeMiddleware = [ … 'password_expired' => \App\Http\Middleware\PasswordExpired::class, ];
Ну вот и все. Осталось только применить наш middleware к определенным роутам. Для этого переходим в routes/web.php И добавляем группу роутов к которой мы применяем наш Middleware. Например, у нас есть роут:
Route::get('/cabinet', function () { return 'cabinet'; });
Изменяем:
Route::middleware(['password_expired'])->group(function () { Route::get('/cabinet ', function () { return 'cabinet'; });
Ну вот и все.
Шаг 4. Создание конфигурации.
Следующее требование менять срок действия пароля из конфигурационного файла. Запросто. Давайте откроем файл config/auth.php и добавим в массив еще один элемент:
'password_expires_days' => 30,
Теперь немного изменим наш middleware:
public function handle($request, Closure $next) { $user = $request->user(); $password_changed_at = new Carbon(($user->password_changed_at) ? $user->password_changed_at : $user->created_at); if (Carbon::now()->diffInDays($password_changed_at) >= config('auth.password_expires_days') { return redirect()->route('password.expired'); } return $next($request); }
Вот и все.
Вывод.
Мы с вами реализовали проверку истекшего пароля в Laravel, используя Middleware. Вынесли время действия пароля в конфигурационный файл.
Спасибо за статью. Очень интересно было почитать)