На одном из проектов написанных на БУС реализованы формы обратной связи через стандартный компонент bitrix:web.form.
Поверх этого мы использовали валидацию полей с помощью JS, маску телефона на основе jquery.maskedinput.js и Google Recaptcha 2.0, которая инициализировалась и включалась с помощью настроек компонента форм.
Мы столкнулись с тем, что ежедневно в формы обратной связи приходил спам, который обходил все наши валидаторы и проходил капчу.
Проанализировав ситуацию мы сошлись на том, что это - массовые рассылки спама, не смотря на наличие Recaptcha. Боты давно научились обходить капчу заполнением, это не секрет, но из интересных особенностей заметили, что в поле "Телефон" попадают буквенные значения, а значит, наш валидатор и маска не работают.
Идея того, что боты загружают страницу без JS - показалась сомнительной т.к. без верификации капчи - форма не отправляется.
Случай максимально странный, казалось бы, с JavaScript - бот встретит валидацию и маски, без JavaScript - не увидит капчу, а значит не сможет отправить данные.
Решили не искать логику там, где её нет - начали перебирать разные варианты дополнительной защиты формы. Сначала внедрили валидацию и маски в тело страницы, не помогло.
Повесили Recaptcha 3, не помогло.
Писали валидатор внутри битрикса, использовали паттерны - не помогло.
То есть для обычного посетителя - форма отправится без проблем, это поле он не увидит, а для бота без JS - будет обязательное поле, которое выключено, а значит кнопка submit неактивна.
Битрикс как остановить спам
Окончательное решение - во все формы добавлять невидимые (НЕ display none, которые боты умеют определять, а невидимые благодаря стилизации) поля, при заполнении которых мы понимаем, что это спам и данные не уходят на почту.Код необходимо разместить в init.php, работать будет абсолютно на всех формах вызванных с помощью компонента bitrix:form
Файл bitrix/php_interface/init.php или если вы молодцы и проект у вас собран правильно - local/php_interface/init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler("main", "OnEndBufferContent", "OnEndBufferWebFormAntiSpam");
function OnEndBufferWebFormAntiSpam(&$content)
{
$xStyle = '';
$content = str_ireplace('', $xStyle.'', $content);
$findField = 'addEventHandler('form', 'onBeforeResultAdd', 'onBeforeResultAddWebFormAntiSpam');
function onBeforeResultAddWebFormAntiSpam($WEB_FORM_ID, &$arFields, &$arrVALUES){
global $APPLICATION;
if(!empty($arrVALUES['last_name'])){
$APPLICATION->ThrowException('Отказать.');
}
}
Сначала мы добавили стилей для нашего поля, далее нашли поле WEB_FORM_ID (есть в каждой форме, выполненной на стандартном компоненте) и добавили рядом input с названием last_name (фамилия), для ботов - это поле так же в приоритете, а значит шанс того, что оно будет заполнено - высок.
Далее, после нажатия кнопки "отправить", но перед отправкой сервером, используя событие onBeforeResultAdd мы проверяем поле last_name на заполненное. Если заполнено - ThrowException, письмо не ушло.
По результатам - за неделю ни одного спам-письма, несмотря на попытки.
Решение в конечном итоге будет выглядеть так:
<input class="xname name" tabindex="-1" autocomplete="off" type="text" name="last_name" value="">
<input type="hidden" name="WEB_FORM_ID" value="2">
<input type="hidden" name="sessid" id="sessid_1" value="12581jsdoisjdg"> <input type="hidden" name="web_form_submit" value="Y">