Битрикс и reCapcha. Боремся с роботами, а не с людьми

Что такое капча и какие с ней бывают проблемы

Что такое “капча” сегодня знает даже школьник. А вот “зачем” — хорошо знают владельцы сайтов.

Любая капча это палка о двух концах. Сложная капча хорошо защищает от спам-роботов, но она же мешает клиентам отправить заявку или заказ. Простая - наоборот, удобна для людей и уязвима для роботов. Пример капчи
На помощь, с девизом “Просто для людей, сложно для роботов”, спешит Google reCapthca.

Забегая вперед, скажу что мы сделали свой клевый/универсальный/не требующий программирования модуль для замены стандартной капчи на reCaptcha для Битрикс.

Google-капча: принцип работы

reCAPTCHA представляет из себя небольшой виджет. Для большинства пользователей он выглядит как просто поле с галочкой. Галочка reCAPTCHA
В некоторых случаях потребуется пройти небольшое задание, чтобы доказать что Вы не робот. Например, Google может попросить Вас выбрать из списка изображения с определенным объектом, или выделить на одном изображении нужный объект: Выбор картинок в reCAPTCHA
Потребуют ли от Вас проходить такое задание или нет зависит от того, что Google знает о Вас.

Если Ваши действия в интернете похожи на человеческие (вы читаете разные сайты, авторизованы в почте, вводите поисковые запросы) - скорее всего проходить квест не потребуется.

Работа большинства капч основана на задаче распознавания текста. Роботы плюс-минус научились их разгадывать. Google reCaptcha 2.0 пошла дальше и использует задачи распознавания изображений. Пока роботы угадывают изображения сильно хуже людей.

Как подключить reCAPTHCA в Битрикс

Мы бы хотели найти такую волшебную таблетку, которая решит эту задачу. Но наше исследование показывает что пока ее нет. Поэтому кроме обзора MarketPlace-решений мы опишем наше видение архитектурно-правильных вариантов такой интеграции.

Решения из MarketPlace

Маркетплейс предлагает несколько решений для подключения рекапчи. Среди них есть платные и бесплатные. Все обещают примерно одинаковую функциональность: включение и отключение рекапчи на всем сайте буквально в один клик. Нужно только зарегистрировать Ваш домен на сайте www.google.com/recaptcha и вписать 2 полученных ключа в настройках модуля.

Наиболее больные острые вопросы при подключении рекапчи:
  • поддержка нескольких капч на странице;
  • капча во всплывающем окне, которое потенциально загружается по AJAX.
Как же справляются с этими задачами готовые решения Marketplace?

Мы проверили на примере пары самых популярных (по количеству установок) решений которые можно попробовать без покупки.

Модуль “reCaptchaFree

Доступные настройки:
  • поддержка многосайтовости - можно настроить рекапчу для каждого сайта в отдельности;
  • возможность отключения рекапчи без удаления модуля. Правда здесь обнаружилась проблема - при деактивации рекапчи с помощью этой настройки скрипты js все равно подключались на странице;
  • настройка визуального отображения виджета и т.д.
Порадовало, что модуль оказался работоспособен на формах в модальном окне и AJAX-форме. Однако, для работы некоторых компонентов в режиме ajax требуется вносить изменения в код шаблона, что неудобно, если таких компонентов на сайте много.

Также после установки модуля потребуется отредактировать шаблон компонента, чтобы избавиться от подобных ситуаций:
Защита от автоматических сообщений
Как выяснилось позже, это необходимо проделать для всех модулей.

Модуль “Google ReCaptcha – улучшенная капча и защита от ботов

Состав настроек невелик: только ключи. Поэтому для отключения рекапчи придется удалять модуль. Что касается работоспособности, то с обычными формами модуль справился неплохо. А вот с некоторыми компонентами в режиме Ajax вызвал ошибки. Другие модули (например, Google reCAPTCHA | продвинутая капча) из MarketPlace не предоставляют возможность для тестирования.

Как сделать самим

Если по каким-то причинам нас не устраивают готовые решения  или нам требуется рекапча только в одной форме на сайте, то мы можем сами ее подключить. Мы знаем 3 правильных способа это сделать.

Кастомизация компонента и шаблона компонента

Капча выводится в шаблонах некоторых компонентов. Правильность ее ввода проверяется в компоненте. Почему так? - Потому что: Так архитектурно правильно. MVC и все такое. Шаблон компонента кешируется и выполняется не всегда. Следовательно, без кастомизации компонента здесь никак не обойтись. Прежде, чем кастомизировать компонент, для работы с капчей удобно создать отдельный класс.

class GoogleReCaptcha

{

public static function getPublicKey() { return ‘your_public_key’;}

public static function getSecretKey() { return ‘your_secret_key’;}

/**

   * @return array - if validation is failed, returns an array with errors, otherwise - empty array. This format is expected by component.

   */

  public static function checkClientResponse()

  {

      $context = \Bitrix\Main\Application::getInstance()->

getContext();

      $request = $context->getRequest();

      $captchaResponse = $request->getPost("g-recaptcha-response");

      if($captchaResponse)

      {

          $url = 'https://www.google.com/recaptcha/api/siteverify';

          $data = array('secret' => static::getSecretKey(), 'response'

=> $captchaResponse);

          $httpClient = new HttpClient();

          $response = $httpClient->post($url,$data);

          if($response)

              $response = \Bitrix\Main\Web\Json::

decode($response,true);

          if(!$response['success']) {

              return $response['error-codes'];

          }

          return array();

      }

      return array(‘no captcha response’);

  }

}


Пример подключение рекапчи в форму регистрации Используем компонент bitrix:main.register. В этом компоненте предусмотрена стандартная капча. Скопируем компонент в наше пространство имен директории  /bitrix/components/. Найдем в коде компонента проверку ввода каптчи. Фрагмент из файла  component.php:

// check captcha

   if ($arResult["USE_CAPTCHA"] == "Y")

   {

       if (!$APPLICATION->CaptchaCheckCode($_REQUEST["captcha_word"], $_REQUEST["captcha_sid"]))

           $arResult["ERRORS"][] = GetMessage("REGISTER_WRONG_CAPTCHA");

   }

В данном фрагменте заменим проверку стандартной капчи на нашу проверку рекаптчи  Google:

if ($arResult["USE_CAPTCHA"] == "Y")

   {

       $errorMessages = GoogleReCaptcha::checkClientResponse();

if( !empty($errorMessages)))

           $arResult["ERRORS"][] = $errorMessages;

   }

Затем отредактируем шаблон компонента. Заменим вывод стандартной капчи на рекапчу:

Фрагмент из файла template.php:

<div class="g-recaptcha" data-sitekey="<?=GoogleReCaptcha::getPublicKey()?>">

Изменения только компонента недостаточно для работы капчи. Также необходимо подключить скрипт для взаимодействия с сервисом. Сделать это следует в файле component_epilog.php компонента.

\Bitrix\Main\Page\Asset::getInstance()->addString(

“<script src='https://www.google.com/recaptcha/api.js'></script>”);

В результате получим:


Подключение рекапчи с помощью JS

Можно попробовать пойти другим путем, чтобы не пришлось кастомизировать десятки компонентов. А именно:

  1. При отображении страницы в браузере найдем и подменим все bitrix-капчи на reCAPTCHA.

  2. Будем ловить заполнение форм на любой страницы (все POST-хиты). Если в запросе есть разгаданная пользователем reCAPTHCA заставим битрикс думать, что пользователь разгадал bitrix-капчу.

Вот так будет выглядеть JS-часть с использованием jQuery.

//Находим все битриксовые капчи

b_captcha_sid = $("[name='captcha_sid']");

if (b_captcha_sid.length > 0) {

  b_captcha_img = $(b_captcha_sid).siblings('img');

  if(b_captcha_img.length >0) {

//Убираем изображения

      $(b_captcha_img).remove();

      $(b_captcha_sid).each(function (index) {

         //Вставляем на место изображений рекапчу

          tmp = document.createElement('div');

          tmp.innerHTML = "<div class='g-recaptcha' data-sitekey='your_site_key'></div>";

          g_recaptcha = tmp.firstChild;

          g_recaptcha = (this.parentElement).

appendChild(g_recaptcha);

         //Отрисовываем виджет рекапчи

          if(typeof (grecaptcha) != "undefined") {

              grecaptcha.render(g_recaptcha,{

                  'sitekey': 'your_site_key'

              });

          }

      });

  }

}

//Скрываем все поля ввода слова капчи

b_captcha_word = $("[name='captcha_word']");

if (b_captcha_word.length > 0) {

  $(b_captcha_word).hide();

}

Компоненты на странице ничего не знают про Google капчу и при отправке формы будут проверять правильность ввода стандартной. Соответственно нам нужно симитировать ее ввод.

Данные HTTP запросов компоненты получают из суперглобальных переменных $_POST, $_GET, $_REQUEST. Для проверки капчи компонент ожидает переменные captcha_sid и captcha_word. captcha_word при отправке формы с рекапчей будет пустая. Ее мы возьмем из таблицы b_captcha.

Изменять суперглобальные переменные  нужно до отработки компонентов. Для этого можно использовать события, которые вызываются в процессе выполнения страницы, а именно OnPageStart или OnBeforeProlog. Вот так будет выглядеть PHP-часть:

$context = \Bitrix\Main\Application::getInstance()-&gt;

getContext();

$request = $context->getRequest();

$captchaResponse = $request->getPost("g-recaptcha-response");

if($captchaResponse)

{

if(!\GoogleReCaptcha::checkClientResponse())

 {

$captchaSid = $request->getPost("captcha_sid");

    if($captchaSid)

    {

//Т.к. нет API, позволяющего получить слово капчи по ID, делаем запрос напрямую к БД

       $dbRes = \Bitrix\Main\Application::getConnection()->query(

"SELECT CODE FROM b_captcha WHERE id='".$captchaSid."'");

       if($res = $dbRes->fetch())

       {

          if($res['CODE'])

          {

             $_REQUEST['captcha_word'] = $_POST['captcha_word'] = $res['CODE'];

          }

       }

    }

 }

}


Если пользователь вводил рекапчу и успешно ее прошел, то мы подставляем верное значение captcha_word. В противном случае при проверке капчи компонент выдаст ошибку.

Подключение рекапчи с помощью OnEndBufferContent

Замену капчи мы можем осуществлять не только на клиентской части с помощью JS, но и на серверной. Для этого снова используем событие выполнения страницы OnEndBufferContent.

Пример замены капчи на стороне сервера:

public static function OnEndBufferContent(&$content)

{

//Для форм загружаемых по ajax добавляем вызов скрипта рендера рекапчи

$renderScript = "";

$htmlId = "";

$context = \Bitrix\Main\Application::getInstance()->getContext();

$request = $context->getRequest();

if($request->isAjaxRequest())

 {

    $id = uniqid ('r_');

    $renderScript = "<script>renderRecaptcha('$id');</script>";

    $htmlId = 'id="'.$id.'"';

 }

//Убираем  поля для ввода слова

$content = preg_replace( '/<input[^<>]*name\s?=\s?.captcha_word.[^<>]*>/' , '' , $content );

//Все изображения заменяем на рекапчу

$content = preg_replace ( '/<img[^<>]*src\s?=\s?.\/bitrix\/tools\/captcha\.php\?(captcha_code|captcha_sid)=[^<>]*>/' , "<div class='g-recaptcha' data-sitekey=''your_site_key'' ".$htmlId."></div>".$renderScript ,  $content);

}

Функция рендера рекапчи на JavaScript выглядит так:

renderRecaptcha = function(elementId) {

if (typeof (grecaptcha) != "undefined") {

    var element = document.getElementById(elementId);

    if(element != undefined && element.childNodes.length == 0) {

       grecaptcha.render(element, {

          'sitekey': 'your_site_key'

       });

    }

 }

}

Ее следует добавить в шаблон сайта.

Дальнейшая проверка капчи осуществляется также как во втором способе - по событию OnPageStart или OnBeforeProlog.

Сообщения об ошибках

При замене капч разом на всем сайте (способы 2 и 3) нам потребуется изменить сообщение об ошибке ввода капчи. Чтобы избежать подобных ситуаций:
Все сообщения записываются в языковых переменных. Их мы можем переопределить глобально. Создадим файл /bitrix/php_interface/user_lang/ru/lang.php.

Для компонента добавления и редактирования элемента инфоблока запись в файле будет выглядеть так:

$MESS['/bitrix/components/bitrix/iblock.element.add.form/lang/ru/component.php']['IBLOCK_FORM_WRONG_CAPTCHA'] = "Не пройдена проверка от автоматического заполнения";

Выводы

Использование рекапчи Google обладает неоспоримыми преимуществами по сравнению с стандартной битриксовой капчей: жизнь пользователей сильно упрощается, а безопасность сайта не страдает.

Задача выглядит не очень сложной. Тем не менее в найденных на MarketPlace решениях она решена с огрехами. Мы исправили эту досадную ситуацию и представляем Вам наш модуль для замены капчи Битрикс на Google reCaptcha.
Оцените статью
09.06.2017
Понравилась статья?
Поделитесь ссылкой с друзьями и коллегами!

Статьи по теме

10.01.2023
Как битриксоиды в React уходили Приятно познакомиться, мы битриксоиды. Да-да, те самые которые: вообще не модные, пишут НЕ на Laravel и Symphony, ...
10.01.2023
Товарная дистрибуция 30 лет спустя. Как программисты изменили продажи крупного бизнеса «Я думал, что буду строить банк, а на самом деле построил ИТ-компанию» Олег Тиньков, безработный Есть такая штука — товарная дистри...
10.01.2023
Как мы решили выпускать собственный продукт через CustDev и у нас получилось Собственный продукт как фиксация компетенции&nbsp; В развитии крупных компаний-аутсорсеров наступает момент, когда они уже обросли опытом и компетенциями ...
19.12.2022
Учимся настраивать свою почту, не наступая на чужие грабли: Postfix + msmtp + сайт Привет, меня зовут Никита, я backend-разработчик в компании ИНТЕРВОЛГА. Работаю в компании уже 3 года, и за этот срок достаточно часто мне приходилось вози...
23.11.2022
Развитие B2B-платформы: готовые функции, задачи в работе и планы на будущее В этой статье расскажем о текущем развитии B2B-Платформы — нашего инструмента для автоматизации работы с оптовыми клиентами. Что сделали, что в работе, что...
05.10.2022
Личный кабинет подрядчика: ускорение процесса сбора документов работников на объектах компании ЕВРАЗ в 15 раз Получение документации от подрядчика – долговременно, сложно, утомительно Подрядчикам приходится пройти настоящее бюрократическое испытание, чтобы получить д...

Мы работаем по одному из двух форматов:

  • аренда команды (от 2 человек, не менее 3 месяцев);
  • итерации с фиксированной ценой (1-3 месяца длительностью).

ИНТЕРВОЛГА предоставляет:

  • регулярные онлайн-планерки с заказчиком;
  • квалифицированных специалистов;
  • организованную команду (находятся в одном помещении, что упрощает решение рабочих вопросов);
  • полную прозрачность и регулярность отчетов о результатах.

Для доработок и развития мы предлагаем формат 100 часов в месяц. Что можно сделать за это время:

  • новые нетиповые страницы или раздел;
  • 2 отчета с индивидуальными настройками;
  • 3-5 веб-сервисов интеграции;
  • замудренный калькулятор и т.п.

Поддержка «чтобы все работало как часы» стоит 45 тысяч рублей в месяц и описана тут.

Хочешь получать лучшие статьи от INTERVOLGA раз в месяц?
Подпишись на рассылку — спамить не будем