1c_bitrix_captcha

Битрикс CAPTCHA – валидация форм и защита от спама

Когда ваш сайт засыпают спамом, на помощь приходит CAPTCHA. В данном примере вы увидите как в своих формах можно применять этот замечательный инструмент, который помогает бороться с ботами и хламом в почте или инфоблоках.

CAPTCHA в своих формах при помощи 1C-Битрикс

В формах у 1С-Битрикс капча присутствует, и включается в настройках компонента. Рассмотрим пример генерации CAPTCHA для своих веб-форм при помощи встроенных инструментов в данную CMS.

Для понимания разобьем весь процесс на 3 шага.

ШАГ I. Разбираем HTML код формы:

<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");?>

<?include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php");
$cpt = new CCaptcha();
$captchaPass = COption::GetOptionString("main", "captcha_password", "");
if(strlen($captchaPass) <= 0)
{
    $captchaPass = randString(10);
    COption::SetOptionString("main", "captcha_password", $captchaPass);
}
$cpt->SetCodeCrypt($captchaPass);
?>

<form id="writeUs" method="post" action="/ajax/writeUs.php" class="zayavkaform js-form">
	<div class="zayavwrap">
		<h1>Написать нам</h1>
		<input name="contactmail" type="hidden" value="<?=$email?>">
		<p>Контактное лицо<span>*</span></p>            
		<input required="" name="fio" type="text" class="inptext">    

		<p>Номер телефона<span>*</span></p>            
		<input required="" name="phone" type="text" class="inptext">    

		<p>Введите код с картинки<span>*</span></p>
		<input class="captchaSid" name="captcha_code" value="<?=htmlspecialchars($cpt->GetCodeCrypt());?>" type="hidden">
		<table>
			<tr>
				<td><input class="inptext" required="" id="captcha_word" name="captcha_word" type="text"></td>
				<td><img class="captchaImg" src="/bitrix/tools/captcha.php?captcha_code=<?=htmlspecialchars($cpt->GetCodeCrypt());?>"></td>
			</tr>
		</table>
		<input type="submit" value="ОТПРАВИТЬ">
		<div class="error-text"></div>
	</div>
</form>

<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>

В самом начале мы генерируем капчу, если всё сработало правильно, в вашей форме появится поле для ввода. Также, подключается класс для работы с капчей.

Как это выглядит:

битрикс капча

ШАГ II. Теперь пишем js, который отвечает за отправку формы (jquery – ajax):

$('.js-form').on('submit', function(){
    var $this = $(this);
    $.ajax({
        url: $this.attr('action'),
        type: 'post',
        cache: false,
        data: $this.serialize(),
    }).done(function(data){
        if (data == 'error') {
            $this.find('.error-text').text('Вы не правильно заполнили поля!');
        } else {
            //$this.html('<h1>'+data+'</h1>');
            parent.$.fancybox.close();
            $.fancybox({
                href: '#finish',
                closeBtn: true
            });
        }
        console.log(data);
    }).error(function(){
        console.log('There was an error');
    });

    return false;
});

Какие в скрипте есть нюансы:
1. В action мы записываем ссылку на файл, который обрабатывает данные из формы и записывает их в админку Битрикса;
2. Выводим на месте ошибки что поля заполнены не верно в случае если это так – когда js переменная data = error;
3. При помощи плагина fancybox, мы сначала закрываем окно с нашей формой, а потом открываем окно с благодарностью, универсальное для всех форм.

Подключение jquery на сайте – обязательно.

ШАГ III. Страница для нашей формы – /ajax/writeUs.php :

<?php require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

if(!$APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"])) {
  echo 'error';
} else {

  CModule::IncludeModule("iblock");

  $el = new CIBlockElement;
  $arLoadProductArray = Array(
      "MODIFIED_BY" => $USER->GetID(),
      "IBLOCK_SECTION_ID" => false,
      "IBLOCK_ID" => 31,
      "NAME" => htmlspecialchars($_POST['fio']).' ('.htmlspecialchars($_POST['phone']).')',
      "PREVIEW_TEXT" => 'Контактное лицо: '.htmlspecialchars($_POST["fio"])."\r\n".
                        'Название организации: '.htmlspecialchars($_POST["name"])."\r\n".
                        'Телефон: '.htmlspecialchars($_POST["phone"])."\r\n".
                        'E-mail: '.htmlspecialchars($_POST["email"])."\r\n".
                        'Вопрос: '.htmlspecialchars($_POST["text"]),
      "ACTIVE" => "Y"
  );
  $ELEMENT_ID = $el->Add($arLoadProductArray);

  $arEventFields = array(
      "EMAIL_FROM"   => FORM_SENDER_EMAIL,
      "EMAIL_TO"     => FORM_RECEIVE_EMAIL,
      "NAME"         => htmlspecialchars($_POST["fio"]),
      "COMPANY_NAME" => htmlspecialchars($_POST["name"]),
      "PHONE"        => htmlspecialchars($_POST["phone"]),
      "EMAIL"        => htmlspecialchars($_POST["email"]),
      "QUESTION"     => htmlspecialchars($_POST["text"])
  );

  CEvent::Send("SEND_FEEDBACK", "s1", $arEventFields);

  echo '<span class="form-success">Спасибо! Форма отправлена.</span>';

}

В самом начале мы проверяем – правильная ли у нас капча, если нет то передаем слово error и скриптом проверяем есть у нас ошибка или нет. Разбирать подробно как добавить поля в инфоблок, отправить почтовое сообщение в данной статье мы не будем (но самые любопытные смогут прочитать код и понять как это делается 🙂 ).

Пара слов о блоке с формой:

<p>Введите код с картинки<span>*</span></p>
<input class="captchaSid" name="captcha_code" value="<?=htmlspecialchars($cpt->GetCodeCrypt());?>" type="hidden">
<table>
	<tr>
		<td><input class="inptext" required="" name="captcha_word" type="text"></td>
		<td><img class="captchaImg" src="/bitrix/tools/captcha.php?captcha_code=<?=htmlspecialchars($cpt->GetCodeCrypt());?>"></td>
	</tr>
</table>

Как вы видите, у нас есть скрытый инпут в который мы пишем значение капчи и тег с картинкой, в которую и передается CAPTCHA ID.

Как в битриксе обновить капчу без перезагрузки страницы

В нашей форме уже есть “защита от спама”. Очень нужная вещь, обновление картинки – на случай если плохо читается, или просто не видно.

Взглянем на наш код теперь:

<div class="captcha-block">
	<p>Введите код с картинки<span>*</span></p>
	<input class="captchaSid" name="captcha_code" value="<?=htmlspecialchars($cpt->GetCodeCrypt());?>" type="hidden">
	<table>
		<tr>
			<td><input class="inptext" required="" id="captcha_word" name="captcha_word" type="text"></td>
			<td><img class="captchaImg" src="/bitrix/tools/captcha.php?captcha_code=<?=htmlspecialchars($cpt->GetCodeCrypt());?>"></td>
		</tr>
	</table>
	<a class="captcha-link reloadCaptcha" href="#">Поменять картинку</a>
</div>

Как видно из кода выше, мы добавили текстовую ссылку на смену картинки. Теперь напишем скрипт, который будет менять код для родительского блока captcha-block:

<script type="text/javascript">
   $(document).ready(function(){
      $('.captcha-block').on('click', '.reloadCaptcha', function(){
      	var $parent = $(this).closest('.captcha-block');
         //$parent.find('.whiteBlock').show();
         $.getJSON('/ajax/reload_captcha.php', function(data) {
            $parent.find('.captchaImg').attr('src','/bitrix/tools/captcha.php?captcha_sid='+data);
            $parent.find('.captchaSid').val(data);
            //$parent.find('.whiteBlock').hide();
         });
         return false;
      });
   });
</script>

Чуть ниже код, который отвечает за генерацию капчи, а пока что давайте разберемся что тут происходит.
1. Мы пишем что скрипт срабатывает когда загружена все элементы страницы – документ рэди;
2. Регистрируем обработчик событий по клику на ссылку с классом reloadCaptcha в блоках с классом captcha-block ;
3. Записываем объект в переменную $parent, который и является нашим родительским блоком (у каждой формы он свой, а нам надо менять только внутри того, где мы кликнули);
4. Далее мы отправляем запрос на страницу, которая находится в корне сайта, в папке /ajax/ – имя страницы вы уже поняли 🙂 ;
5. Полученный результат (data) – мы записываем и в переменную внутри тега img и в скрытый инпут, который в дальнейшем и проверяется при отправке формы.

Код для страницы /ajax/reload_captcha.php:

<?php
require($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/prolog_before.php');
echo json_encode($APPLICATION->CaptchaGetCode()); 
?>

Внимательный читатель догадался, показ и исчезновение блока .white-block находится в комментариях. Из кода я его убрал – в другой статье речь идет про обычный прелоадер во время выполнения запроса к серверу. Но на проекте был настолько быстрый отклик, что в прелоадере просто отпала вся необходимость, и капча генерировалась очень быстро.

Благодарю автора статьи за отличное решение, ссылка на оригинал:
https://dev.1c-bitrix.ru/community/webdev/user/61475/blog/2818/#like

Если на вашем сайте необходимо выполнить работы по защите от спама в веб-формах при помощи CAPTHCA, обращайтесь ко мне за помощью.

автор: Dmitriy

З 2011 року займаюся веб-розробкою. Зараз я – PHP Full Stack Developer.
Обговорити ваш проект, а також дізнатися більше про мене ви можете на цьому сайті:
dev.forwww.com

Email: dmitriyribka@gmail.com

Залишити відповідь