Авторизация
Во фреймворке MV авторизация реализуется с помощь класса Auth и может быть добавлена к уже существующей модели при помощи передачи массива параметров.
Параметры авторизации
Создадим модель с минимальным количеством полей и добавим к ней функционал авторизации по email и паролю.
//Файл models/accounts.model.php
class Accounts extends Model
{
protected $name = 'Аккаунты пользователей';
protected $model_elements = [
['Имя', 'char', 'name', ['required' => true]],
['Email', 'email', 'email', ['required' => true, 'unique' => true]],
['Пароль', 'password', 'password', ['required' => true]]
];
protected $auth_settings = [
'login_field' => 'email',
'password_field' => 'password'
];
}Ниже представлены дополнительные параметры для настройки авторизации с более широким функционалом:
- active_field - название поля для определение активности записи, тип данных bool
- remember_me - функционал ‘Запомнить меня’ для автологина с помощью cookie (срок жизни в днях)
- last_login_field - название поля типа date_time для фиксации даты последнего логина пользователя
- token_field - поле с индивидуальным токеном каждого аккаунта, тип данных char
- watch_ip - отслеживать ip адрес пользователя (и разлогинивать если изменился)
- watch_browser - отслеживать браузер адрес пользователя (и разлогинивать если изменился)
//Файл models/accounts.model.php
class Accounts extends Model
{
...
protected $auth_settings = [
'login_field' => 'email',
'password_field' => 'password',
'active_field' => 'active',
'remember_me' => true,
'remember_me_lifetime' => 30,
'last_login_field' => 'last_login_date',
'token_field' => 'extra_token',
'recover_password_lifetime' => 3600,
'watch_ip' => true,
'watch_browser' => true
];
}Регистрация и авторизация
//Создаем пользователя (после регистрации или через админ панель)
$account = $mv -> Accounts -> getEmptyRecord();
$account -> name = 'User';
$account -> email = 'user@example.com';
$account -> password = 'mypassword';
$account -> save();
//Авторизуем пользователя
Auth::useModel(Accounts::class);
$user = Auth::login('user@example.com', 'mypassword');
//Также можно авторизовать пользователя с помощью объектов Record или Form
//$record - объект класса Record модели Accounts
$user = Auth::login($record);
//$form - объект формы с полями 'email' и 'password'
$user = Auth::login($form);
//Если аккаунт найден, то $user - объект класса Record модели Accounts
Debug::pre($user -> all());
//Проверяем есть ли авторизованный пользователь класса Accounts
Auth::useModel(Accounts::class);
$user = Auth::check();
//Разлогинивание пользователя
Auth::useModel(Accounts::class);
Auth::logout();
//Результат проверки - null
$user = Auth::check();Автологин пользователя по cookie
//Функционал 'Запомнить меня на данном устройстве'
//$user - авторизованный пользователь
//Опция 'remember_me' включена в настройках авторизации
Auth::useModel(Accounts::class);
Auth::remember($user);
//Попытка авторизации пользователя по cookie
Auth::useModel(Accounts::class);
$user = Auth::loginWithRememberMeCookie();
//Отмена автологина и удаление cookie
Auth::useModel(Accounts::class);
Auth::forget();Проверка авторизации
Для удобства разработки можно перенести проверку авторизации в файл before-view.php и тогда аккаунт пользователя будет доступен во всех шаблонах проекта.
//Файл views/before-view.php
Auth::useModel(Accounts::class);
if(null === $user = Auth::check())
$user = Auth::loginWithRememberMeCookie();
//Если аккаунт авторизован мы можем, например, поставить метку в Registry
if(is_object($user))
{
Registry::set('UserIsAuthorized', true);
...
}Разлогинивание logout
Для реализации разлогинивания пользователя помимо вызова метода Auth::logout() рекомендуется отправить на нужный URL форму методом POST с передачей токена для подтверждения выхода пользователя.
<?
//Создание хэш-кода для logout (пользователь должен быть авторизован)
Auth::useModel(Accounts::class);
$token = Auth::generateLogoutToken();
?>
//Небольшая форма с кнопкой выхода
<form method="POST" action="/account/logout">
<input type="hidden" name="logout_token" value="<? echo $token; ?>">
<button>Выйти</button>
</form>
<?
//Проверка токена в файле шаблона для URL /account/logout
Auth::useModel(Accounts::class);
if('' !== $token = Http::fromPost('logout_token', ''))
if(Auth::hasAuthorizedUser() && $token === Auth::generateLogoutToken())
{
Auth::logout();
Http::redirect('/login');
}
?>Восстановление пароля
Для восстановления пароля пользователя обычно используется отправка email со специальной ссылкой, при переходе на которую пользователю предлагается создать новый пароль. Также учитывается срок жизни такой ссылки для предотвращения повторного перехода на сброс пароля.
Главным элементом ссылки является сгенерированный хэш-код, по которому можно найти запись пользователя в базе данных.
Для добавления функционала по восстановлению пароля в MV не требуется вносить изменения в структуру базы данных. Все нужные параметры передаются зашифрованными в код ссылки.
//Создание хэш-кода для ссылки
//$user - объект класса Record модели Accounts
//Срок жизни ссылки указывается в параметре 'recover_password_lifetime' (по умолчанию 1 час)
Auth::useModel(Accounts::class);
$token = Auth::generatePasswordRecoveryToken($user);
//Создание ссылки для отправки по email
$link = Service::getAbsoluteHttpPath('/recover/'.$token);
$message = 'Ваша ссылка для восстановления пароля '.$link;
Email::send($user -> email, 'Восстановление пароля', $message);
//При переходе по ссылке извлекаем код из второй части URL и ищем по ней запись пользователя
$token = $mv -> router -> getUrlPart(1);
Auth::useModel(Accounts::class);
if(null !== $user = Auth::checkPasswordRecoveryToken($token))
{
//Если аккаунт найден, то показываем форму для нового пароля
$form = new Form([
['Новый пароль', 'password', 'password' ['required' => true]],
['Повтор пароля', 'password', 'password_repeat', [
'required' => true,
'must_match' => 'password'
]
]);
//Если форма заполнена правильно сохраняем новый пароль пользователя
if($form -> isSubmitted() && $form -> isValid())
{
Auth::recoverPassword($user, $form -> password);
Http::redirect('/login');
}
}
Предыдущий раздел
AJAX