Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.
Решил несколько разнообразить нашу замечательную 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");
|
Даже самому порою было проблематично ввести.
Проиллюстрируем что у нас получилось:
Математическая

Последовательность

Цветовая

Стандартная
Назад в раздел
Подписаться на новые материалы раздела:
Загрузка...
Наверх