Битрикс и reCapcha. Боремся с роботами, а не с людьми
- Что такое капча и какие с ней бывают проблемы
- Google-капча: принцип работы
- Как подключить reCAPTHCA в Битрикс
- Выводы
Что такое капча и какие с ней бывают проблемы
Что такое “капча” сегодня знает даже школьник. А вот “зачем” — хорошо знают владельцы сайтов.Любая капча это палка о двух концах. Сложная капча хорошо защищает от спам-роботов, но она же мешает клиентам отправить заявку или заказ. Простая - наоборот, удобна для людей и уязвима для роботов.
На помощь, с девизом “Просто для людей, сложно для роботов”, спешит Google reCapthca.
Забегая вперед, скажу что мы сделали свой клевый/универсальный/не требующий программирования модуль для замены стандартной капчи на reCaptcha для Битрикс.
Google-капча: принцип работы
reCAPTCHA представляет из себя небольшой виджет. Для большинства пользователей он выглядит как просто поле с галочкой.В некоторых случаях потребуется пройти небольшое задание, чтобы доказать что Вы не робот. Например, Google может попросить Вас выбрать из списка изображения с определенным объектом, или выделить на одном изображении нужный объект:
Потребуют ли от Вас проходить такое задание или нет зависит от того, что Google знает о Вас.
Если Ваши действия в интернете похожи на человеческие (вы читаете разные сайты, авторизованы в почте, вводите поисковые запросы) - скорее всего проходить квест не потребуется.
Работа большинства капч основана на задаче распознавания текста. Роботы плюс-минус научились их разгадывать. Google reCaptcha 2.0 пошла дальше и использует задачи распознавания изображений. Пока роботы угадывают изображения сильно хуже людей.
Как подключить reCAPTHCA в Битрикс
Мы бы хотели найти такую волшебную таблетку, которая решит эту задачу. Но наше исследование показывает что пока ее нет. Поэтому кроме обзора MarketPlace-решений мы опишем наше видение архитектурно-правильных вариантов такой интеграции.Решения из MarketPlace
Маркетплейс предлагает несколько решений для подключения рекапчи. Среди них есть платные и бесплатные. Все обещают примерно одинаковую функциональность: включение и отключение рекапчи на всем сайте буквально в один клик. Нужно только зарегистрировать Ваш домен на сайте www.google.com/recaptcha и вписать 2 полученных ключа в настройках модуля.Наиболее
- поддержка нескольких капч на странице;
- капча во всплывающем окне, которое потенциально загружается по AJAX.
Мы проверили на примере пары самых популярных (по количеству установок) решений которые можно попробовать без покупки.
Модуль “reCaptchaFree”
Доступные настройки:- поддержка многосайтовости - можно настроить рекапчу для каждого сайта в отдельности;
- возможность отключения рекапчи без удаления модуля. Правда здесь обнаружилась проблема - при деактивации рекапчи с помощью этой настройки скрипты js все равно подключались на странице;
- настройка визуального отображения виджета и т.д.
Также после установки модуля потребуется отредактировать шаблон компонента, чтобы избавиться от подобных ситуаций:
Как выяснилось позже, это необходимо проделать для всех модулей.
Модуль “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
Можно попробовать пойти другим путем, чтобы не пришлось кастомизировать десятки компонентов. А именно:
-
При отображении страницы в браузере найдем и подменим все bitrix-капчи на reCAPTCHA.
-
Будем ловить заполнение форм на любой страницы (все POST-хиты). Если в запросе есть разгаданная пользователем reCAPTHCA заставим битрикс думать, что пользователь разгадал bitrix-капчу.
//Находим все битриксовые капчи
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();
}
Данные HTTP запросов компоненты получают из суперглобальных переменных $_POST, $_GET, $_REQUEST. Для проверки капчи компонент ожидает переменные captcha_sid и captcha_word. captcha_word при отправке формы с рекапчей будет пустая. Ее мы возьмем из таблицы b_captcha.
Изменять суперглобальные переменные нужно до отработки компонентов. Для этого можно использовать события, которые вызываются в процессе выполнения страницы, а именно OnPageStart или OnBeforeProlog. Вот так будет выглядеть PHP-часть:
$context = \Bitrix\Main\Application::getInstance()->
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.
Статьи по теме
- аренда команды (от 2 человек, не менее 3 месяцев);
- итерации с фиксированной ценой (1-3 месяца длительностью).
- регулярные онлайн-планерки с заказчиком;
- квалифицированных специалистов;
- организованную команду (находятся в одном помещении, что упрощает решение рабочих вопросов);
- полную прозрачность и регулярность отчетов о результатах.
- нагруженный интернет-магазин;
- личный кабинет;
- оптовые продажи — B2B-платформа;
- маркетплейс;
- технический аудит сайта;
- Битрикс24 — корпоративные HR-порталы;
- Битрикс24 — построение CRM-системы;
- Битрикс24 — личные кабинеты сотрудников;
- Битрикс24 — аудит портала;
- 1С — интеграция с другими системами;
- 1С — доработка системы;
- маркетинг — комплексное интернет-продвижение;
- маркетинг — продвижение для B2B.