206 lines
8.5 KiB
PHP
206 lines
8.5 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Фильтр для проверки авторизации
|
||
*
|
||
* action: login(password, login)
|
||
* action: logout()
|
||
*/
|
||
// В класс авторизации передавать обьект для управления пользователем
|
||
// Вынести в отдельный файл
|
||
namespace ctiso\Filter;
|
||
use ctiso\Filter\Filter,
|
||
ctiso\HttpRequest,
|
||
ctiso\Settings,
|
||
ctiso\Registry,
|
||
ctiso\Database,
|
||
ctiso\Role\User,
|
||
ctiso\Collection,
|
||
ctiso\Path;
|
||
|
||
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;
|
||
public $mode = 'ajax';
|
||
public $user;
|
||
public $role;
|
||
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;
|
||
}
|
||
|
||
private function enter($result)
|
||
{
|
||
$this->user = $result;
|
||
$random = rand(0, 1024 * 1024);
|
||
$this->role->setSID($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();
|
||
}
|
||
|
||
public function execute(HttpRequest $request)
|
||
{
|
||
$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) {
|
||
$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;
|
||
}
|
||
}
|