ADD: users_auth_tokens and rememberMe()

Начало работы с rememberMe, сохранение в базу, запомнить и т.д.
This commit is contained in:
Evg 2021-03-24 10:46:51 +03:00
parent 24976129e1
commit 240759ba6c
5 changed files with 179 additions and 26 deletions

View file

@ -14,9 +14,7 @@ class AdminController extends \MainController
if(!$account = Request::getSession('account')) {
redirect('/');
}
// Если TL участника не равен 5 (персонал) - редирект
if(!$isAdmin = UserModel::isAdmin($account['user_id'])) {
redirect('/');

View file

@ -356,31 +356,10 @@ class Base
return $gram_num_record;
}
# Регистрация информации о пользователе
protected function loginCookie($Key, $uid, $login, $trust_level)
{
$loginTime = time();
setcookie('dev_login', $login, $loginTime + 604800, '/');
$loginEncode = $this->secret->encrypt(json_encode(array(
$uid,
$login,
$trust_level,
$loginTime
)), $Key);
setcookie('dev_secure', $loginEncode, $loginTime + 604800, '/');
}
// Длина строки
public static function getStrlen($str)
{
return mb_strlen($str, "utf-8");
}
}

View file

@ -255,6 +255,169 @@ class UserModel extends \MainModel
}
////// ЗАПОМНИТЬ МЕНЯ
////// Работа с токенамм
public function rememberMe($uid)
{
// НАСТРОЕМ НАШ СЕЛЕКТОР, ВАЛИДАТОР И СРОК ДЕЙСТВИЯ
// Селектор действует как уникальный идентификатор, поэтому нам не нужно
// сохранять идентификатор пользователя в нашем файле cookie
// валидатор сохраняется в виде обычного текста в файле cookie, но хэшируется в бд
// если селектор (id) найден в таблице auth_tokens, мы затем сопоставляем валидаторы
$rememberMeExpire = 30;
$selector = random_string('crypto', 12);
$validator = random_string('crypto', 20);
$expires = time() + 60 * 60 * 24 * $rememberMeExpire;
// Установим токен
$token = $selector . ':' . $validator;
// Массив данных
$data = [
'user_id' => $uid,
'selector' => $selector,
'hashedvalidator' => hash('sha256', $validator),
'expires' => date('Y-m-d H:i:s', $expires),
];
// ПРОВЕРИМ, ЕСТЬ ЛИ У ИДЕНТИФИКАТОРА ПОЛЬЗОВАТЕЛЯ УЖЕ НАБОР ТОКЕНОВ
// Мы действительно не хотим иметь несколько токенов и селекторов для
// одного и того же идентификатора пользователя. В этом нет необходимости,
// так как валидатор обновляется при каждом входе в систему
// поэтому проверим, есть ли уже маркер, и перепишем, если он есть.
// Следует немного снизить уровень обслуживания БД и устранить необходимость в спорадических чистках.
$result = self::GetAuthTokenByUserId($uid);
// Если не вставить
if (empty($result)) {
self::insertToken($data);
}
// Если есть обновление
else {
self::updateToken($data, $uid);
}
// set_Cookie
setcookie(
"remember",
$token,
$expires,
$GLOBALS['conf']['cookiePath'],
$GLOBALS['conf']['cookieDomain'],
$GLOBALS['conf']['cookieSecure'],
$GLOBALS['conf']['cookieHTTPOnly'],
);
}
// Каждый раз, когда пользователь входит в систему, используя свой файл cookie «запомнить меня»
// Сбросить валидатор и обновить БД
public static function rememberMeReset($uid, $selector)
{
// Получаем по селектору
$existingToken = self::GetAuthTokenBySelector($selector);
if (empty($existingToken)) {
return $this->rememberMe($uid);
}
$rememberMeExpire = 30;
$validator = random_string('crypto', 20);
$expires = time() + 60 * 60 * 24 * $rememberMeExpire;
// Установить
$token = $selector . ':' . $validator;
// Если установлено значение true, каждый раз, когда пользователь посещает сайт
// и обнаруживает файл cookie новая дата истечения срока действия
// устанавливается с помощью параметра $rememberMeExpire - выше
$rememberMeRenew = true;
if ($rememberMeRenew) {
// Массивы данных установим
$data = [
'hashedvalidator' => hash('sha256', $validator),
'expires' => date('Y-m-d H:i:s', $expires),
];
} else {
$data = [
'hashedvalidator' => hash('sha256', $validator),
];
}
self::UpdateSelector($data, $selector);
setcookie(
"remember",
$token,
$expires,
$GLOBALS['conf']['cookiePath'],
$GLOBALS['conf']['cookieDomain'],
$GLOBALS['conf']['cookieSecure'],
$GLOBALS['conf']['cookieHTTPOnly'],
);
}
// Поля в таблице users_auth_tokens
// auth_id, auth_user_id, auth_selector, auth_hashedvalidator, auth_expires
public static function getAuthTokenByUserId($uid)
{
return XD::select('*')->from(['users_auth_tokens'])
->where(['auth_user_id'], '=', $uid)->getSelectOne();
}
public static function insertToken($data)
{
XD::insertInto(['users_auth_tokens'], '(', ['auth_user_id'], ',', ['auth_selector'], ',', ['auth_hashedvalidator'], ',', ['auth_expires'], ')')->values( '(', XD::setList([$data['user_id'], $data['selector'], $data['hashedvalidator'], $data['expires']]), ')' )->run();
return true;
}
public static function updateToken($data, $uid)
{
XD::update(['users_auth_tokens'])->set(['auth_user_id'], '=', $data['user_id'], ',', ['auth_selector'], '=', $data['selector'], ',', ['auth_hashedvalidator'], '=', $data['hashedvalidator'], ',', ['auth_expires'], '=', $data['expires'])->where(['auth_user_id'], '=', $uid)->run();
return true;
}
public function DeleteTokenByUserId($uid)
{
XD::deleteFrom(['users_auth_tokens'])->where(['auth_user_id'], '=', $uid)->run();
return true;
}
public function UpdateSelector($data, $selector)
{
XD::update(['users_auth_tokens'])->set(['auth_user_id'], '=', $data['user_id'], ',', ['auth_selector'], '=', $data['selector'], ',', ['auth_hashedvalidator'], '=', $data['hashedvalidator'], ',', ['auth_expires'], '=', $data['expires'])->where(['auth_selector'], '=', $data['selector'])->run();
return true;
}
// Получаем токен аутентификации по селектору
public static function getAuthTokenBySelector($selector)
{
return XD::select('*')->from(['users_auth_tokens'])
->where(['selector'], '=', $selector)->getSelectOne();
}
// Настройка оповещений
public static function getNotificationSettingByUid($uid)
{

View file

@ -21,5 +21,8 @@ return array(
'smtpport' => 25,
'timezone' => 'Europe/Moscow',
'allow_ip' => '', // Закрыть доступ в админку по ip
'cookie_key' => 'd414kgdogkokd4G9fr998ecf8427e'
);
'cookieDomain' => '',
'cookiePath' => '/',
'cookieSecure' => false,
'cookieHTTPOnly' => false
);

View file

@ -23,6 +23,16 @@ SET time_zone = "+00:00";
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `users_auth_tokens` (
`auth_id` int(11) NOT NULL AUTO_INCREMENT,
`auth_user_id` int(11) NOT NULL,
`auth_selector` varchar(255) NOT NULL,
`auth_hashedvalidator` varchar(255) NOT NULL,
`auth_expires` datetime NOT NULL,
PRIMARY KEY (`auth_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Структура таблицы `comments`