Периодически возникал вопрос по защите от ботов различных форм на сайте: регистрация, авторизация, подписка на рассылку, обратная связь, комментирование и т.д.

Стандартная капча — бесполезная, ботами она проходится «на раз», а пользователям создает проблемы.

Оптимальное решение это использовать Google reCAPTCHA v2 или v3. Обе версии Google reCAPTCHA — отличный вариант. Это лучшее, что сейчас доступно на рынке из понятных и надежных решений к тому же бесплатных.

Основная проблема у обеих версий — при подключении значительно снижаются баллы по PageSpeed Insight на 20-30.

Пример reCAPTCHA v2 — требует угадывать картинки

Пример reCAPTCHA v3 — не требует от пользователя действий, в фоне анализирует его поведение

Важный для меня момент — не создавать проблемы реальным пользователям, т.к. я сам не большой любитель угадывать транспортные средства в reCAPTCHA v2, поэтому мой выбор v3.

Итак две проблемы Google reCAPTCHA v3, которые необходимо решить:

  • висящий логотип в нижнем правом углу;
  • потеря 20-30 баллов по Google PageSpeed Insight.

Висящий логотип

В лицензионном соглашении Google допускает убрать логотип, скрыв его через CSS.

.grecaptcha-badge {
	visibility: hidden;
}

Взамен под каждой формой написать «Защита от спама reCAPTCHA Конфиденциальность и Условия использования» со ссылками на соответствующие страницы Google.


Потеря баллов по Google PageSpeed Insight

При подключении javascript-файла от reCAPTCHA v3, сильно снижаются баллы по Google PageSpeed Insight. Для меня это было критично. Думаю, что это связано с анализом поведения пользователей (подобное снижение происходит при использовании вебвизора в Яндекс.Метрике).

На хорошо оптимизированных ресурсах можно потерять 20-30 баллов. Поэтому использовать её на отдельных страницах, где скорость не важна (например, контактов) можно и без модификаций. Для использования на всём сайте (например, для защиты сквозной формы авторизации или подписки на рассылку) желательно сделать модификацию.

Я придумал вариант инициализировать reCAPTCHA v3 по клику на поля формы. По умолчанию javascript-файл от reCAPTCHA v3 не загружаю, и только если пользователь поставил курсор на одно из полей формы выполняю его загрузку. Скорее всего данный метод снижает точность определения реальных пользователей, но проблем не возн��кало. Для моих задач данной точности хватает.

Данную методику начал применять сначала на веб-формах 1С-Битрикс, далее для сквозных форм авторизации и подписки на рассылку на сайтах без Битрикса.

Ввиду того, что 1С-Битрикс публичная CMS, расскажу в общих чертах на её примере — про методику и возможный вариант использования. Более тонкую настройку можно сделать под свои потребности.

Использование Google reCAPTCHA v3 в веб-формах 1С-Битрикс


1. Форму вызываем стандартным компонентом bitrix:form и делаем 2 дополнения:

  • Заменяем кнопку button type=submit на обычный button type=button
  • добавляем hidden поле name=g_recaptcha_response



2. Добавляем в javascript-файл сайта или компонента инициализацию reCAPTCHA при клике по полям формы (в этом примере я предполагаю, что вы используете jQuery):

$('body').on('click','form input, form textarea', function() {
	if (typeof(grecaptcha) == 'undefined') {
		var grecaptcha_s = document.createElement('script');
		grecaptcha_s.src = 'https://www.google.com/recaptcha/api.js?render=<PUBLIC_KEY>';

		var grecaptcha_h = document.getElementsByTagName('script')[0];
	grecaptcha_h.parentNode.insertBefore(grecaptcha_s,grecaptcha_h);
	}
});

3. Добавляем отслеживание клика по кнопке button в форме. Далее внутри, используем пример описанный в документации Google. Он заполняет поле g_recaptcha_response, которое мы будет использовать на последнем шаге для валидации пользователя.

$('body').on('click','form button[name="web_form_submit"]', function() {
	grecaptcha.ready(function() {
		grecaptcha.execute('<PUBLIC_KEY>',{action: 'feedback'}).then(
			function(token) {
				$('form input[name="g_recaptcha_response"]').val(token);

				var form_obj = $('form');
				var event_obj = form_obj.get(0);

				BX.fireEvent(event_obj,'submit');	
				event_obj.submit();
			}
		);
	});
});

4. Отслеживаем event onBeforeResultAdd в init.php

Перед отправкой результатов формы делаем обращение на сервер Google с вашим <PRIVATE_KEY>, и значением из hidden поля g_recaptcha_response из формы.

В ответ получаем баллы данного пользователя:

  • 1 это точно человек
  • 0 точно робот
  • Больше 0.5 можно считать человеком

AddEventHandler("form","onBeforeResultAdd","onBeforeResultAddHandler");

function onBeforeResultAddHandler($WEB_FORM_ID,$arFields,$arrVALUES)
{
	global $APPLICATION;

	$g_recaptcha_response = $arrVALUES["g_recaptcha_response"];
	if (!empty($g_recaptcha_response))
	{
		$response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=<PRIVATE_KEY>&response=".$g_recaptcha_response."&remoteip=".$_SERVER["REMOTE_ADDR"]),true);
			

		$g_recaptcha_response_check = false;

		if (($response["success"] and $response["score"] >= 0.5 and $response["action"] == 'feedback']))
		{
			$g_recaptcha_response_check = true;
		}

		if (!$g_recaptcha_response_check)
		{
			$APPLICATION->ThrowException('Не пройдена проверка Google reCAPTCHA v3.</a>');
		}
	}
	else
	{
		$APPLICATION->ThrowException('Не пройдена проверка Google reCAPTCHA v3.');
	}
}

В заключение


Данную методику можно использовать на любых сайтах и формах вне зависимости от CMS. Я привёл общие методики работы, которые можно применять в своём проекте.

Подобным образом можно поступить и с Google reCAPTCHA v2, инициализировать по клику на форме и просить пользователя установить галочку «Я не робот» и отгадать картинки, если потребуется. В данном случае это также сэкономит баллы по PageSpeed Insight и даст пользователю инструмент (выбирать картинки), чтобы доказать, что он не робот. Но как я уже говорил выше для меня самое важное, это не создавать пользователю преград.