Доброго всем дня!
Продолжим наши уроки по усовершенствованию Инстанта. Сегодня мы будем изучать и усовершенствовать первую ветку Инстанта. Вторую пока трогать не будем.И будем делать все по взрослому 😊
Итак, как я уже писал для многоуважаемого Fuze, одним из неудобств (и даже проблем) первого Инстанта является её система авторизации. Как вы заметили несколько версий назад появилась следующая фича — если вы ошибаетесь со вводом пароля, на следующем разе CMS предлагает вам ввести капчу. Этого сделано для того, чтобы хакер(скорее крякер) не "крякнул" пароль пользователя CMS простым перебором.
Вот об этом и поговорим на этом и следующем уроке.
Итак, я хочу (да и много где пишут об этом различные уважаемые и вежливые человеки) сделать следующую вещь — чтобы капча появилась только на третий неправильный ввод пароля. Мне лично очень не нравится писать капчу, когда я ошибся паролем. "Хакать" систему мы не будем, мы сделаем плагин, который это все и будет делать.
Итак, что нам нужно
1) увеличить на 1 счетчик неверных вводов если пароль неверный
2) если счетчик больше указанного числа (это кто-то подбирает, точно, точно) — вывести капчу
3) если пароль введен верно — сбросить счетчик
В Инстанте 1.10.x появилась замечательная возможность заменить экшен (action) компонента или выполнить какие-то действия перед этим экшеном. Вот этим мы у будем пользоваться. Взяв как пример встроенный плагин P_DEMO_ROUTE и посмотрев как работает вызов экшена в ядре приходим к следующему выводу.
Наш плагин, пусть он называется p_authcnt будет обрабатывать всего два события:
USER_LOGIN — который вызывается после успешной авторизации
GET_REGISTRATION_ACTION_AUTH — экшен AUTH компонента REGISTRATION — как раз он обрабатывает вход и перед его вызовом мы и будем воплощать свои фантазии. Заменять нам его не нужно, нам только нужно направить его работу в нужное нам русло.
Итак добавим в наш плагин строки
$this->events[] = 'GET_REGISTRATION_ACTION_AUTH';
$this->events[] = 'USER_LOGIN';
и конфиг по умолчанию:
$this->config['P_BADAUTHCOUNT'] = 3;
это три неверных ввода
Далее при установке плагина добавим поле в таблицу cms_users для подсчета входов
это кусочек из метода install()
Так начнем с простого чтобы нам сбросить счетчик при верном входе напишем обработчик события USER_LOGIN
И сразу приведу код метода события GET_REGISTRATION_ACTION_AUTH
Метод работает очень просто — он получает признак вывода капчи $antibruteforce, если он равен 1 — значит был неверный вход (задачка на дом — а где он ставится в единичку?), выключает его временно, увеличивает на 1 счетчик и тут же проверяет, если он стал больше указанного нами в конфиге числа входов — включает признак обратно (чтобы капча все-таки вылезла)
И отдает управление далее "старому" экшену AUTH.
Вот и все
Что мы хотели то и в принципе получили. НО, все также плохо и неудобно. Признак капчи лежит в сессии, если хакер будет постоянно удалять куку сессии — смысла от нашей капчи нет.
Я сделал следующую версию плагина, которая работает на ajax и выводит капчу только на N-ный неверный ввод без перезагрузки страницы. В чем разница спросите вы — а разница в том, что от сессии уже ничего не зависит и вот тут хакер уже и не отвертится от ввода капчи.
Но об этом на следующем уроке.
Полный текст плагина разобранного на этом уроке
скачать тут
делалось на 1.10.3
P.S. далее может быть (все зависит от вашего желания)
— авторизация ajax с подсчетом неверных входов и выводом капчи по необходимости (возможность использования в окне)
— защита от подбора увеличением времени ввода пароля
— учет неверных вводов для каждой сессии и общего количества сессий с подбором в опред.промежуток времени и защита от этого
— регистрация ajax (тут вот в предыдущем посте и окошко сделали 😊)
— прикрутка ко всему этому регистрации через соцсети на своем сайте и через сайт поставщик
Демо demo1.instantdemo.ru
Юзеры:
fedor
vasya
пароли 1234, 12345678 или 123456 — сами подберите 😊
Продолжим наши уроки по усовершенствованию Инстанта. Сегодня мы будем изучать и усовершенствовать первую ветку Инстанта. Вторую пока трогать не будем.
Итак, как я уже писал для многоуважаемого Fuze, одним из неудобств (и даже проблем) первого Инстанта является её система авторизации. Как вы заметили несколько версий назад появилась следующая фича — если вы ошибаетесь со вводом пароля, на следующем разе CMS предлагает вам ввести капчу. Этого сделано для того, чтобы хакер(скорее крякер) не "крякнул" пароль пользователя CMS простым перебором.
Вот об этом и поговорим на этом и следующем уроке.
Итак, я хочу (да и много где пишут об этом различные уважаемые и вежливые человеки) сделать следующую вещь — чтобы капча появилась только на третий неправильный ввод пароля. Мне лично очень не нравится писать капчу, когда я ошибся паролем. "Хакать" систему мы не будем, мы сделаем плагин, который это все и будет делать.
Итак, что нам нужно
1) увеличить на 1 счетчик неверных вводов если пароль неверный
2) если счетчик больше указанного числа (это кто-то подбирает, точно, точно) — вывести капчу
3) если пароль введен верно — сбросить счетчик
В Инстанте 1.10.x появилась замечательная возможность заменить экшен (action) компонента или выполнить какие-то действия перед этим экшеном. Вот этим мы у будем пользоваться. Взяв как пример встроенный плагин P_DEMO_ROUTE и посмотрев как работает вызов экшена в ядре приходим к следующему выводу.
Наш плагин, пусть он называется p_authcnt будет обрабатывать всего два события:
USER_LOGIN — который вызывается после успешной авторизации
GET_REGISTRATION_ACTION_AUTH — экшен AUTH компонента REGISTRATION — как раз он обрабатывает вход и перед его вызовом мы и будем воплощать свои фантазии. Заменять нам его не нужно, нам только нужно направить его работу в нужное нам русло.
Итак добавим в наш плагин строки
$this->events[] = 'GET_REGISTRATION_ACTION_AUTH';
$this->events[] = 'USER_LOGIN';
и конфиг по умолчанию:
$this->config['P_BADAUTHCOUNT'] = 3;
это три неверных ввода
Далее при установке плагина добавим поле в таблицу cms_users для подсчета входов
это кусочек из метода install()
if (!$inDB->isFieldExists('cms_users', 'authcnt')){ $inDB->query("ALTER TABLE `cms_users` ADD `authcnt` INT DEFAULT 0");
private function eventUserLogin($user) { $inCore = cmsCore::getInstance(); $inDB = cmsDatabase::getInstance(); $inDB->query("UPDATE cms_users SET authcnt = 0 WHERE id = '{$user['id']}'"); }
private function eventAuth() { if( !cmsCore::inRequest('logout') ) { $inCore = cmsCore::getInstance(); $inDB = cmsDatabase::getInstance(); $antibruteforce = cmsUser::sessionGet('anti_brute_force'); $login = cmsCore::request('login', 'str', ''); $passw = cmsCore::request('pass', 'str', ''); if ($login=="") { $login = cmsUser::sessionGet('login','user'); } // логин или почта? if (!$login || !$passw){ $where_login = "login = '{$login}'"; } else { $where_login = "email = '{$login}'"; } if ($antibruteforce == 1) { $antibruteforce = 0; $inDB->query('UPDATE cms_users SET authcnt = authcnt + 1 WHERE '.$where_login); cmsUser::sessionDel('anti_brute_force'); } $cnt = $inDB->get_field('cms_users',$where_login,'authcnt'); echo("Количество неверных вводов пароля:".$cnt." "); if ($cnt >= $this->config['P_BADAUTHCOUNT']) { $antibruteforce = 1; cmsUser::sessionPut('anti_brute_force', 1); } } } return false; }
И отдает управление далее "старому" экшену AUTH.
Вот и все
Что мы хотели то и в принципе получили. НО, все также плохо и неудобно. Признак капчи лежит в сессии, если хакер будет постоянно удалять куку сессии — смысла от нашей капчи нет.
Я сделал следующую версию плагина, которая работает на ajax и выводит капчу только на N-ный неверный ввод без перезагрузки страницы. В чем разница спросите вы — а разница в том, что от сессии уже ничего не зависит и вот тут хакер уже и не отвертится от ввода капчи.
Но об этом на следующем уроке.
Полный текст плагина разобранного на этом уроке
/******************************************************************************/ // // // Auth Counter and Protector // // // // // // based on InstantCMS 2007-2014 // // produced by Krot, // // // // free license // // // /******************************************************************************/ class p_authcnt extends cmsPlugin { // ==================================================================== // public function __construct(){ parent::__construct(); // Информация о плагине $this->info['plugin'] = 'p_authcnt'; $this->info['title'] = 'Auth Counter'; $this->info['description'] = 'Подсчет неверных авторизаций'; $this->info['author'] = 'krot'; $this->info['version'] = '1.10'; // События, которые будут отлавливаться плагином // $this->events[] = 'GET_ROUTE_REGISTRATION'; // это нам пока не надо $this->events[] = 'GET_REGISTRATION_ACTION_AUTH'; $this->events[] = 'USER_LOGIN'; $this->config['P_BADAUTHCOUNT'] = 3; } // ==================================================================== // /** * Процедура установки плагина * @return bool */ public function install(){ $inDB = cmsDatabase::getInstance(); if (!$inDB->isFieldExists('cms_users', 'authcnt')){ $inDB->query("ALTER TABLE `cms_users` ADD `authcnt` INT DEFAULT 0"); } return parent::install(); } // ==================================================================== // /** * Процедура обновления плагина * @return bool */ public function upgrade(){ return parent::upgrade(); } // ==================================================================== // /** * Обработка событий * @param string $event * @param mixed $data * @return mixed */ parent::execute(); switch ($event){ // case 'GET_ROUTE_USERS': $data = $this->eventGetRoutes($data); break; // это пока не надо case 'GET_REGISTRATION_ACTION_AUTH': $data = $this->eventAuth(); break; case 'USER_LOGIN': $this->eventUserLogin($data); break; } return $data; } // ==================================================================== // private function eventGetRoutes($routes) { // формируем массив по аналогии с router.php '_uri' => '/^registration\/login$/i', 'do' => 'auth' ); // перебираем массив $add_routes, занося каждый в начало входного массива $routes foreach($add_routes as $route){ } return $routes; } // ==================================================================== // private function eventAuth() { if( !cmsCore::inRequest('logout') ) { $inCore = cmsCore::getInstance(); $inDB = cmsDatabase::getInstance(); $antibruteforce = cmsUser::sessionGet('anti_brute_force'); // это тоже вроде не надо $login = cmsCore::request('login', 'str', ''); $passw = cmsCore::request('pass', 'str', ''); if ($login=="") { $login = cmsUser::sessionGet('login','user'); } // если нет логина или пароля, показываем форму входа if (!$login || !$passw){ $where_login = "login = '{$login}'"; } else { $where_login = "email = '{$login}'"; } if ($antibruteforce == 1) { $antibruteforce = 0; $inDB->query('UPDATE cms_users SET authcnt = authcnt + 1 WHERE '.$where_login); cmsUser::sessionDel('anti_brute_force'); } $cnt = $inDB->get_field('cms_users',$where_login,'authcnt'); echo("Количество неверных вводов пароля:".$cnt.""); if ($cnt >= $this->config['P_BADAUTHCOUNT']) { $antibruteforce = 1; cmsUser::sessionPut('anti_brute_force', 1); } } } return false; } private function eventUserLogin($user) { $inCore = cmsCore::getInstance(); $inDB = cmsDatabase::getInstance(); $inDB->query("UPDATE cms_users SET authcnt = 0 WHERE id = '{$user['id']}'"); } // ==================================================================== // }
делалось на 1.10.3
P.S. далее может быть (все зависит от вашего желания)
— авторизация ajax с подсчетом неверных входов и выводом капчи по необходимости (возможность использования в окне)
— защита от подбора увеличением времени ввода пароля
— учет неверных вводов для каждой сессии и общего количества сессий с подбором в опред.промежуток времени и защита от этого
— регистрация ajax (тут вот в предыдущем посте и окошко сделали 😊)
— прикрутка ко всему этому регистрации через соцсети на своем сайте и через сайт поставщик
Демо demo1.instantdemo.ru
Юзеры:
fedor
vasya
пароли 1234, 12345678 или 123456 — сами подберите 😊
Реклама #
Крот 10 лет назад #
поправьте пжл.
lokanaft 10 лет назад #
Raiden 10 лет назад #
Александр 10 лет назад #
Крот 10 лет назад #
P.S. честно, я не проверял на совместимость
Александр 10 лет назад #
Крот 10 лет назад #