phplibrary/src/Filter/Login.php

216 lines
8.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Фильтр для проверки авторизации
*/
namespace ctiso\Filter;
use ctiso\Filter\Filter;
use ctiso\HttpRequest;
use ctiso\Settings;
use ctiso\Registry;
use ctiso\Database;
use ctiso\Role\User;
use ctiso\Collection;
use ctiso\Path;
use ctiso\Database\PDOStatement;
// В класс авторизации передавать обьект для управления пользователем
// Вынести в отдельный файл
class Login extends Filter
{
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
const AUTH_MAX_ATTEMPT = 10;
const AUTH_LAST_ATTEMPT_TIMER = 600;
/** @var string */
public $mode = 'ajax';
/** @var PDOStatement */
public $user;
/** @var User */
public $role;
/** @var Registry */
public $config;
function __construct($processor, User $role, Registry $config) {
parent::__construct($processor);
$this->role = $role;
$this->config = $config;
}
/**
* Проверка авторизации
* @param HttpRequest $request
* @return Boolean Авторизовани пользователь или нет
*/
public function isLoggin(HttpRequest $request)
{
// Авторизация
session_start();
switch ($request->getAction()) {
// Авторизация по постоянному паролю
case 'login':
$login = $request->get('login', '') ;
$password = $request->get('password');
$result = $this->role->getUserByLogin($login); // Поиск по логину
if ($result) {
$userPassword = $this->role->getUserPassword($result);
if ($this->role->access == 'site_root' && defined('PARENT_PATH')) {
$s = new Settings(PARENT_PATH . '/settings.json');
$s->read();
$dsn = $s->readKey(['system', 'dsn']);
$db = Database::getConnection($dsn);
$user = $db->fetchOneArray("SELECT * FROM users WHERE login = :login", ['login' => $login]);
$userPassword = $user['password'];
} /*else if (time() - $result->getInt('lastupdate') > 60*60*24*60) {
// Проверить давность пароля, 60 дней
$request->set('error', true);
$request->set('lastupdate', true);
return false;
}*/
// Проверка на количества попыток авторизации
$lastAttempt = $result;
if ($lastAttempt->get('trie_count') >= self::AUTH_MAX_ATTEMPT /*&& time() - $lastAttempt['trie_time'] < self::AUTH_LAST_ATTEMPT_TIMER*/) {
if (time() - $lastAttempt->get('trie_time') < self::AUTH_LAST_ATTEMPT_TIMER) {
$request->set('timeout_error', true);
break;
} else {
$this->role->resetTries($request->get('login'));
}
}
// Извлечнеие пользователя из родительской CMS, для проверки пароля
if (md5($password) == $userPassword) { // password
$this->enter($result);
return true;
} else {
// Обновление количества неудачных попыток входа
$this->role->updateTries($login);
}
}
$request->set('error', true);
break;
case 'logout': // Выход
session_destroy();
break;
// Вход по временному паролю, не используется
/*
case 'enter':
$login = $request->get('login');
$password = $request->get('sid');
$result = $this->role->getUserByLogin($login); // Поиск по логину
if ($result) {
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
if ($password == $temp) {
$this->enter($result);
return true;
}
}
break;
*/
default:
$hash = Authorization::getBrowserSign();
// Если $hash не совпадает $_SESSION['hash'] то удаляем сессию
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME])) {
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME]) {
$this->user = $user = $this->role->getUserById($_SESSION['access']); // Поиск по идентификатору
if ($user && isset($_SESSION['random']) && ($user->get('sid') == $_SESSION['random'])) {
return true;
}
return true;
} else {
session_destroy();
}
}
}
return false;
}
/**
* Вход в систему
* @param PDOStatement $result
*/
private function enter($result): void
{
$this->user = $result;
$random = rand(0, 1024 * 1024);
$this->role->setSID((string)$random, $result);
$_SESSION["group"] = $result->getInt('access');
$_SESSION["access"] = $result->getInt('id_user'); // id_user
$_SESSION["random"] = $random; // id_user
$_SESSION[self::SESSION_BROWSER_SIGN_KEYNAME] = Authorization::getBrowserSign();
$_SESSION["time"] = time();
}
/**
* @return mixed
*/
public function execute(HttpRequest $request): mixed
{
$logged = $this->isLoggin($request);
if ($request->get('action') == 'user_access') {
if ($logged) {
$result = [];
$result['fullname'] = $this->user->getString('patronymic') . " " . $this->user->getString('firstname');
$result['email'] = $this->user->getString('email');
$result['hash'] = sha1(self::SESSION_BROWSER_SIGN_SECRET . $this->user->getString('email'));
return json_encode($result);
} else {
return json_encode("NOT AUTHORIZED");
}
}
if ($request->get('action') == 'relogin') {
if ($logged) {
return json_encode(['result' => 'ok', 'message' => "Авторизация успешна"]);
} else {
return json_encode(['result' => 'fail', 'message' => "Неправильное имя пользователя или пароль"]);
}
}
if (!$logged) {
// Параметры при неправильной авторизации
// Действия по умолчанию !! Возможно переход на форму регистрации
if ($request->get('mode') == 'ajax') {
if (!$this->requestIsWhite($request)) {
return json_encode(['result' => 'fail', 'message' =>"NOT_AUTHORIZED"]);
}
} else {
$request->set('module', 'login');
$request->set('mode', $this->mode);
}
} else if (isset($_SERVER['HTTP_REFERER'])) {
$arr = [];
parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY) ?? '', $arr);
if (isset($arr['back_page']) && $request->get('mode') != 'ajax') {
$request->redirect($arr['back_page']);
}
}
$text = $this->processor->execute($request);
return $text;
}
/**
* Проверка на попадание реквеста в белый список
*/
public function requestIsWhite(Collection $request): bool {
$module = $request->get('module');
$action = $request->get('action');
$moduleDir = explode('\\',$module)[0];
$file = Path::join($this->config->get('system', 'path'), 'modules', $moduleDir, 'filters', 'white.json');
if (file_exists($file)) {
$whiteList = json_decode(file_get_contents($file), true);
if (in_array($action, $whiteList)) {
return true;
}
}
return false;
}
}