Притормаживаем перебор пароля и фиксируем попытки

Фиксировать будем в файлы темповой директории. На каждый логин — свой файл. Частота попыток определяется через разницу текущего времени и времени последней правки файла. Правим файл ActionLogin.class.php, функция EventAjaxLogin:

* Если наш юзер существует, то проверяем разницу между попытками авторизации
$oFName=Config::Get('sys.cache.dir').'login_log-'.$oUser->getLogin().'.txt';

if(file_exists($oFName) && 3>=(time()-filemtime($oFName)))
{
 $this->Message_AddErrorSingle("Sorry, please wait 3 seconds and try again!");
 return;
}

* Если авторизация не прошла, то фиксируем время, ip, ошибочный пароль (лишнее убрать):
$oFile=fopen($oFName,'a');
if($oFile)
{
 fwrite($oFile, date ( DATE_ISO8601, time() ).'['.func_getIp().']='.getRequest('password')."\n" );
 fclose($oFile);
}

Замечания и предложения приветствуются!

5 комментариев

avatar
Если авторизация не прошла,
то откуда:
$oUser->getLogin()

?
создавайте во второй раз уже файл с айпи в имени.
avatar
>то откуда:
если целиком, то так
protected function EventAjaxLogin() {
		/**
		 * Устанвливаем формат Ajax ответа
		 */
		$this->Viewer_SetResponseAjax('json');
		/**
		 * Логин и пароль являются строками?
		 */
		if (!is_string(getRequest('login')) or !is_string(getRequest('password'))) {
			$this->Message_AddErrorSingle($this->Lang_Get('system_error'));
			return;
		}
		/**
		 * Проверяем есть ли такой юзер по логину
		 */
		if ((func_check(getRequest('login'),'mail') and $oUser=$this->User_GetUserByMail(getRequest('login')))  or  $oUser=$this->User_GetUserByLogin(getRequest('login'))) {
			/**
			 * Сверяем хеши паролей и проверяем активен ли юзер
			 */
                        $oFName=Config::Get('sys.cache.dir').'login_log-'.$oUser->getLogin().'.txt';

                        if(file_exists($oFName) && 3>=(time()-filemtime($oFName)))
                        {
                         $this->Message_AddErrorSingle("Sorry, please wait 3 seconds and try again!");
                         return;
                        }

			if ($oUser->getPassword()==func_encrypt(getRequest('password'))) {
				if (!$oUser->getActivate()) {
					$this->Message_AddErrorSingle($this->Lang_Get('user_not_activated', array('reactivation_path' => Router::GetPath('login') . 'reactivation')));
					return;
				}
				$bRemember=getRequest('remember',false) ? true : false;
				/**
				 * Авторизуем
				 */
				$this->User_Authorization($oUser,$bRemember);
				/**
				 * Определяем редирект
				 */
				$sUrl=Config::Get('module.user.redirect_after_login');
				if (getRequestStr('return-path')) {
					$sUrl=getRequestStr('return-path');
				}
				$this->Viewer_AssignAjax('sUrlRedirect',$sUrl ? $sUrl : Config::Get('path.root.web'));
				return;
			}

                        $oFile=fopen($oFName,'a');
                        if($oFile)
                        {
                         fwrite($oFile, date ( DATE_ISO8601, time() ).'['.func_getIp().']='.getRequest('password')."\n" );
                         fclose($oFile);
                        }
		}
		$this->Message_AddErrorSingle($this->Lang_Get('user_login_bad'));
	}

p.s. я вот ща посмотрел ещё раз, и условие «Проверяем есть ли такой юзер по логину» — похоже не совсем правильное, getuserbylogin — дописывали после :))
  • SVK
  • 0
avatar
Может есть смысл после n-ной неправильной попытки вывести капчу?
avatar
Вариант, но правки, имхо, будут более кординальны. Мой вариант — коленочный :)
avatar
ну такой вариант я наблюдаю на всех сайтах более менее посещаемых
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.