Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.
Решил несколько разнообразить нашу замечательную CAPTCHA. Существует множество различных вариантов CAPTCHA, стандартно используется обычный ввод с картинки. В данной статье мы попытаемся добавить еще 3 варианта
1) Математическое выражение
2) Последовательность
3) Цвет
Прежде всего начнем с расширения стандартного класса CAPTCHA, для этого в /bitrix/php_interface/init.php подключим его
и объявим расширяющий класс
Основные переопределяемые функции будут
Т.е. функция установки текста CAPTCHA, как вы можете видеть здесь используется 4 варианта MATH, SEQUENCE, COLOR и default(STANDART).
Второй но не менее важной перегруженной функцией будет функция проверки корректности ввода, она по описанию очень похожа на SetCaptchaCode()
После переопределения мы пишем свои функции установки и обработки CAPTCHA, рассмотрим их принципы.
1. Математическая
Код устанавливается с помощью следующего выражения
где
Конечно же Вы можете дополнить и переопределить данные значения, но иногда стоит подумать а будет ли пользователю высчитывать ваши интегралы?
2. Последовательность
Здесь мы из стандартного набора символов формируем строку и случайным образом выбираем номера символов для последующего ввода.
Набор символов и их последовательность хранится в сессии
где
3. Цветовая
Над текстом мы не стали особо работать и оставили его обычной строкой
Но обработка чутка хитрая
Мы выбираем 2 набора цветов и ответов
Выбираем что будет за вопрос. Цвет фона или текста
и сохраняем полученные данные в сессии для последующей отрисовки и проверки CAPTCHA
Вот принципе и все по формированию CAPTCHA После описание методов установки и проверки - мы допиливаем немного напильником и у нас получается новый улучшенный класс
Далее чтобы наш класс воспринимался и корректно работал придется немного поработать, а именно изменить создание объекта в файле:
/bitrix/tools/captcha.php
с
на
Отлично! наш класс уже вроде должен как работать но, увы это не все изменения. Далее если мы будем работать с формой регистрации, нам надо будет "подкрутить" стандартный компонент "system.auth.registration"
в component.php нам нужно установить свой вызов
Однако нам ничто не мешает сделать это в result_modifer.php
Далее в самом же шаблоне в блоке ввода CAPTCHA добавить вывод своих текстовых сообщений, Я сделал это более банально обычным текстом, но Вам ничего не мешает использовать языковые файлы.
Фу-у-ух, ну вроде все сделали, осталось только включить. Для включения вначале кода нашего класса нам необходимо установить какой вид CAPTCHA мы будем использовать, сделать это можно так
Ну а теперь немного о грустном, из-за ряда подводных камней, пришлось подключать 4 обработчика, которые выполняют обработку и выкидывают EXCEPTION при необходимости, однако это стоит временным отключением проверки CAPTCHA при регистрации стандартным механизмом, а вместо него использовать наш от CAPTCHA. Поэтому если у Вас CAPCTHA всегда используется, то я рекомендую расскоментировать строку:
COption::SetOptionString("main", "captcha_registration", "Y");
PS. Для ценителей изысков, есть режим NO PASARUN!, т.е. постоянная смета типа CAPTCHA. Для этого единожды выполните код
Даже самому порою было проблематично ввести.
Проиллюстрируем что у нас получилось:
Математическая
Последовательность
Цветовая
Стандартная
Назад в раздел
то ждем ваше обращение в нашей службе тех поддержки.
Усиливаем CAPTCHA - Armored
Всем доброго времени суток!Решил несколько разнообразить нашу замечательную CAPTCHA. Существует множество различных вариантов CAPTCHA, стандартно используется обычный ввод с картинки. В данной статье мы попытаемся добавить еще 3 варианта
1) Математическое выражение
2) Последовательность
3) Цвет
Прежде всего начнем с расширения стандартного класса CAPTCHA, для этого в /bitrix/php_interface/init.php подключим его
//include Captcha and extend include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php"); |
и объявим расширяющий класс
if (!class_exists("CCaptchaExt")) { Class CCaptchaExt extends CCaptcha { ... |
Основные переопределяемые функции будут
public function SetCaptchaCode($sid = false) { if(COption::GetOptionString("main", "capctha_shuffle_mode", "N") == "Y") $this->Shuffle(); switch($this->codeType) { case 'MATH': return $this->SetCaptchaMathCode($sid); case 'SEQUENCE': return $this->SetCaptchaSequenceCode($sid); case 'COLOR': return $this->SetCaptchaColorCode($sid); default: return parent::SetCaptchaCode($sid); } } |
Т.е. функция установки текста CAPTCHA, как вы можете видеть здесь используется 4 варианта MATH, SEQUENCE, COLOR и default(STANDART).
Второй но не менее важной перегруженной функцией будет функция проверки корректности ввода, она по описанию очень похожа на SetCaptchaCode()
public function CheckCaptchaCode($userCode, $sid, $bUpperCode = true) { switch($this->codeType) { case 'MATH': return $this->CheckCaptchaMathCode($userCode, $sid, $bUpperCode); case 'SEQUENCE': return $this->CheckCaptchaSequenceCode($userCode, $sid, $bUpperCode); case 'COLOR': return $this->CheckCaptchaColorCode($userCode, $sid, $bUpperCode); default: return parent::CheckCaptchaCode($userCode, $sid, $bUpperCode); } } |
После переопределения мы пишем свои функции установки и обработки CAPTCHA, рассмотрим их принципы.
1. Математическая
Код устанавливается с помощью следующего выражения
$this->code = rand(intval($this->mathMin),intval($this->mathMax)).$this->mathActions[rand(0,count($this->mathActions)-1)].rand(intval($this->mathMin),intval($this->mathMax)); |
где
public $mathActions = array("-", "+"); public $mathMin = 1; public $mathMax = 99; |
Конечно же Вы можете дополнить и переопределить данные значения, но иногда стоит подумать а будет ли пользователю высчитывать ваши интегралы?
2. Последовательность
$this->code = ''; $max = count($this->arChars); $arSequence = array(); for($i=0;$i<$this->sequenceLength;$i++) { $character = $this->arChars[rand(1, $max) - 1]; if(rand(0,1)==1) $arSequence[$i] = $character; $this->code .= $character; } |
Здесь мы из стандартного набора символов формируем строку и случайным образом выбираем номера символов для последующего ввода.
Набор символов и их последовательность хранится в сессии
$_SESSION["CUSTOM_CAPCTHA"]["SEQUENCE"][$this->sid] = $arSequence; |
где
public $sequenceLength = 8; |
3. Цветовая
Над текстом мы не стали особо работать и оставили его обычной строкой
$this->code = "COLOR"; |
Но обработка чутка хитрая
Мы выбираем 2 набора цветов и ответов
$arShemes = array_rand(self::$arColorVariants, 2); |
Выбираем что будет за вопрос. Цвет фона или текста
$answerType = rand(0,1); |
и сохраняем полученные данные в сессии для последующей отрисовки и проверки CAPTCHA
$_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$this->sid] = array( "TYPE" => $answerType==0?'BACKGROUND':'TEXT', "ANSWER" => self::$arColorVariants[$arShemes[$answerType]]["ANSWER"], "COLORS" => $arShemes, ); |
Вот принципе и все по формированию CAPTCHA После описание методов установки и проверки - мы допиливаем немного напильником и у нас получается новый улучшенный класс
<? //COption::SetOptionString("main", "captcha_registration", "Y"); //COption::SetOptionString("main", "capctha_type", "COLOR"); //COption::SetOptionString("main", "capctha_shuffle_mode", "Y"); //include Captcha and extend include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php"); if (!class_exists("CCaptchaExt")) { Class CCaptchaExt extends CCaptcha { public $codeType = NULL; public $mathActions = array("-", "+"); public $mathMin = 1; public $mathMax = 99; public $sequenceLength = 8; static $currentCodeType = NULL; static $arColorVariants = array( array( "ANSWER" => "БЕЛЫЙ", "COLOR" => array(0,0,0), ), array( "ANSWER" => "ЧЕРНЫЙ", "COLOR" => array(255,255,255), ), array( "ANSWER" => "СИНИЙ", "COLOR" => array(0,0,156), ), array( "ANSWER" => "КРАСНЫЙ", "COLOR" => array(255,36,0), ), array( "ANSWER" => "ЖЕЛТЫЙ", "COLOR" => array(255,255,0), ), array( "ANSWER" => "КРАСНЫЙ", "COLOR" => array(35,142,35), ), ); protected function Shuffle() { $arrTypes = array("STANDART", "SEQUENCE", "MATH", "COLOR"); $this->codeType = self::$currentCodeType = $arrTypes[array_rand($arrTypes)]; COption::SetOptionString("main", "capctha_type", $this->codeType); } public function __construct() { $this->codeType = self::$currentCodeType = COption::GetOptionString("main", "capctha_type", "STANDART"); parent::__construct(); } public function InitCode($sid) { global $DB; $res = $DB->Query("SELECT CODE FROM b_captcha WHERE ID = '".$DB->ForSQL($sid,32)."' "); if (!$ar = $res->Fetch()) { $this->SetCaptchaCode($sid); $res = $DB->Query("SELECT CODE FROM b_captcha WHERE ID = '".$DB->ForSQL($sid,32)."' "); if (!$ar = $res->Fetch()) return false; } $this->code = $ar["CODE"]; $this->sid = $sid; $this->codeLength = strlen($this->code); //some additional inits switch($this->codeType) { case 'MATH': break; case 'SEQUENCE': break; case 'COLOR': $colorsID = $_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$this->sid]["COLORS"]; $this->SetBGColor(self::$arColorVariants[$colorsID[0]]["COLOR"]); $this->SetTextColor(self::$arColorVariants[$colorsID[1]]["COLOR"]); break; } return true; } public function SetCaptchaCode($sid = false) { if(COption::GetOptionString("main", "capctha_shuffle_mode", "N") == "Y") $this->Shuffle(); switch($this->codeType) { case 'MATH': return $this->SetCaptchaMathCode($sid); case 'SEQUENCE': return $this->SetCaptchaSequenceCode($sid); case 'COLOR': return $this->SetCaptchaColorCode($sid); default: return parent::SetCaptchaCode($sid); } } protected function SetCaptchaMathCode($sid) { $this->code = rand(intval($this->mathMin),intval($this->mathMax)).$this->mathActions[rand(0,count($this->mathActions)-1)].rand(intval($this->mathMin),intval($this->mathMax)); $this->sid = $sid===false? md5( uniqid(microtime())): $sid; CCaptcha::Add( Array( "CODE" => $this->code, "ID" => $this->sid ) ); } protected function SetCaptchaColorCode($sid) { $this->code = "COLOR"; $this->sid = $sid===false? md5( uniqid(microtime())): $sid; CCaptcha::Add( Array( "CODE" => $this->code, "ID" => $this->sid ) ); $arShemes = array_rand(self::$arColorVariants, 2); $answerType = rand(0,1); $_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$this->sid] = array( "TYPE" => $answerType==0?'BACKGROUND':'TEXT', "ANSWER" => self::$arColorVariants[$arShemes[$answerType]]["ANSWER"], "COLORS" => $arShemes, ); } protected function SetCaptchaSequenceCode($sid) { $this->code = ''; $max = count($this->arChars); $arSequence = array(); for($i=0;$i<$this->sequenceLength;$i++) { $character = $this->arChars[rand(1, $max) - 1]; if(rand(0,1)==1) $arSequence[$i] = $character; $this->code .= $character; } $this->sid = $sid===false? md5( uniqid(microtime())): $sid; CCaptcha::Add( Array( "CODE" => $this->code, "ID" => $this->sid ) ); $_SESSION["CUSTOM_CAPCTHA"]["SEQUENCE"][$this->sid] = $arSequence; } public function CheckCaptchaCode($userCode, $sid, $bUpperCode = true) { switch($this->codeType) { case 'MATH': return $this->CheckCaptchaMathCode($userCode, $sid, $bUpperCode); case 'SEQUENCE': return $this->CheckCaptchaSequenceCode($userCode, $sid, $bUpperCode); case 'COLOR': return $this->CheckCaptchaColorCode($userCode, $sid, $bUpperCode); default: return parent::CheckCaptchaCode($userCode, $sid, $bUpperCode); } } protected function CheckCaptchaMathCode($userCode, $sid, $bUpperCode = true) { global $DB; if (strlen($userCode)<=0 || strlen($sid)<=0) return false; if ($bUpperCode) $userCode = toUpper($userCode); $res = $DB->Query("SELECT CODE FROM b_captcha WHERE ID = '".$DB->ForSQL($sid,32)."' "); if (!$ar = $res->Fetch()) return false; eval('$checkCODE='.$ar["CODE"].';'); if ($checkCODE != $userCode) return false; CCaptcha::Delete($sid); return true; } protected function CheckCaptchaSequenceCode($userCode, $sid, $bUpperCode = true) { global $DB; if (strlen($userCode)<=0 || strlen($sid)<=0) return false; if ($bUpperCode) $userCode = toUpper($userCode); $res = $DB->Query("SELECT CODE FROM b_captcha WHERE ID = '".$DB->ForSQL($sid,32)."' "); if (!$ar = $res->Fetch()) return false; if (join('',$_SESSION["CUSTOM_CAPCTHA"]["SEQUENCE"][$sid]) != $userCode) return false; CCaptcha::Delete($sid); unset($_SESSION["CUSTOM_CAPCTHA"]["SEQUENCE"][$sid]); return true; } protected function CheckCaptchaColorCode($userCode, $sid, $bUpperCode = true) { global $DB; if (strlen($userCode)<=0 || strlen($sid)<=0) return false; if ($bUpperCode) $userCode = str_replace('Ё','Е',toUpper($userCode)); $res = $DB->Query("SELECT CODE FROM b_captcha WHERE ID = '".$DB->ForSQL($sid,32)."' "); if (!$ar = $res->Fetch()) return false; if ($_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$sid]["ANSWER"] != $userCode) return false; CCaptcha::Delete($sid); unset($_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$sid]); return true; } public function SetCode() { return $this->SetCaptchaCode(); } public function CheckCode($userCode, $sid, $bUpperCode = True) { return $this->CheckCaptchaCode($userCode, $sid, $bUpperCode); } static function APPCaptchaGetCode() { $cpt = new CCaptchaExt(); $cpt->SetCode(); return $cpt->GetSID(); } static function APPCaptchaCheckCode($captcha_word, $captcha_sid) { $cpt = new CCaptchaExt(); return $cpt->CheckCode($captcha_word, $captcha_sid); } static function APPBeforeCaptchaCheckCode() { global $APPLICATION; if(COption::GetOptionString("main", "captcha_registration", "N") == "Y") { define("APPCaptchaCheckCode", true); COption::SetOptionString("main", "captcha_registration", "N"); if(!self::APPCaptchaCheckCode($_REQUEST["captcha_word"], $_REQUEST["captcha_sid"])) define("APPCaptchaCheckCodeWRONG", true); } } static function APPOnCaptchaCheckCode($arParams) { if(defined("APPCaptchaCheckCode")) COption::SetOptionString("main", "captcha_registration", "Y"); if(defined("APPCaptchaCheckCodeWRONG")) { global $APPLICATION; $APPLICATION->ThrowException(GetMessage("MAIN_FUNCTION_REGISTER_CAPTCHA")."!<br>"); return false; } return true; } static function APPAfterCaptchaCheckCode() { if(defined("APPCaptchaCheckCode")) COption::SetOptionString("main", "captcha_registration", "Y"); } } } AddEventHandler("main", "OnPageStart", Array("CCaptchaExt", "APPBeforeCaptchaCheckCode")); AddEventHandler("main", "OnBeforeUserRegister", Array("CCaptchaExt", "APPOnCaptchaCheckCode")); AddEventHandler("main", "OnBeforeProlog", Array("CCaptchaExt", "APPAfterCaptchaCheckCode")); AddEventHandler("main", "OnAfterUserRegister", Array("CCaptchaExt", "APPAfterCaptchaCheckCode")); ?> |
Далее чтобы наш класс воспринимался и корректно работал придется немного поработать, а именно изменить создание объекта в файле:
/bitrix/tools/captcha.php
с
$cpt = new CCaptcha(); |
на
$cpt = new CCaptchaExt(); |
Отлично! наш класс уже вроде должен как работать но, увы это не все изменения. Далее если мы будем работать с формой регистрации, нам надо будет "подкрутить" стандартный компонент "system.auth.registration"
в component.php нам нужно установить свой вызов
if ($arResult["USE_CAPTCHA"]) { $arResult["CAPTCHA_CODE"] = htmlspecialchars(CCaptchaExt::APPCaptchaGetCode()); } |
Однако нам ничто не мешает сделать это в result_modifer.php
Далее в самом же шаблоне в блоке ввода CAPTCHA добавить вывод своих текстовых сообщений, Я сделал это более банально обычным текстом, но Вам ничего не мешает использовать языковые файлы.
<td><span class="starrequired">*</span> <? switch(CCaptchaExt::$currentCodeType) { case 'MATH': echo 'Введите результат математического действия с картинки: '; break; case 'SEQUENCE': $sequence = array_keys($_SESSION["CUSTOM_CAPCTHA"]["SEQUENCE"][$arResult["CAPTCHA_CODE"]]); for($i=0, $n = count($sequence); $i<$n; $i++) $sequence[$i]++; echo 'Введите '.join(', ', $sequence).' символ с картинки'; break; case 'COLOR': echo 'Введите цвет '.($_SESSION["CUSTOM_CAPCTHA"]["COLOR"][$arResult["CAPTCHA_CODE"]]["TYPE"]=="TEXT"?'текса':'фона').' с картинки (напр. бежевый): '; break; default: echo 'Введите код с картинки:'; break; } ?> </td> <td><input type="text" name="captcha_word" maxlength="50" value="" /></td> |
Фу-у-ух, ну вроде все сделали, осталось только включить. Для включения вначале кода нашего класса нам необходимо установить какой вид CAPTCHA мы будем использовать, сделать это можно так
COption::SetOptionString("main", "capctha_type", "MATH"); |
Ну а теперь немного о грустном, из-за ряда подводных камней, пришлось подключать 4 обработчика, которые выполняют обработку и выкидывают EXCEPTION при необходимости, однако это стоит временным отключением проверки CAPTCHA при регистрации стандартным механизмом, а вместо него использовать наш от CAPTCHA. Поэтому если у Вас CAPCTHA всегда используется, то я рекомендую расскоментировать строку:
COption::SetOptionString("main", "captcha_registration", "Y");
PS. Для ценителей изысков, есть режим NO PASARUN!, т.е. постоянная смета типа CAPTCHA. Для этого единожды выполните код
COption::SetOptionString("main", "capctha_shuffle_mode", "Y"); |
Даже самому порою было проблематично ввести.
Проиллюстрируем что у нас получилось:
Математическая
Последовательность
Цветовая
Стандартная
Назад в раздел
Подписаться на новые материалы раздела: