1С-Битрикс. Кастомный валидатор поля веб-формы или защита от спама в модуле «Веб-формы» без капчи
Про защиту от спама в регистрации без включения капчи я уже рассказывал. На очереди борьба с ботами в модуле Веб-формы в битриксе, а так же расскажу как написать свой валидатор.
Защищаться будем по схеме, описанной в заметке про регистрацию, а именно: добавляем в форму невидимое поле, если поле заполнено — к нам пришёл бот.
Предположим, форма у вас создана, поля(в понятии модуля форм — «вопросы») для неё заведены и настроены. Заведём ещё одно, служебное, с типом text (поля типа hidden боты иногда игнорируют и не заполняют). В свойствах «Символьный идентификатор» ему надо придумать, как обычному полю, например user или name. Не стоит называть его antibot.
В поле «Текст ответа» чтобы не писать название, можно считерить и вписать неразрывный пробел (в юникоде: Alt + 0160).
Как вы помните, нам нужно проверять поле на пустоту. По умолчание доступны валидаторы:
- [number_ext] Число в пределах
- [text_len] Длина строки
- [number] Целое число
- [INN] Проверка ИНН
Вроде бы подходит валидатор text_len. У него в настройках есть 2 параметра: «Минимальная длина», «Максимальная длина». Но для настройки «Максимальная длина» минимум можно указать 1, а нам нужно 0. Можно поставить и 1, но я решил написать свой валидатор, тем более, что я никогда этого не делал.
Документация по написанию своих валидаторов тут. Там всё просто: пишем PHP-класс с нужными методами и подвешиваем его на нужное событие.
Получился вот такой класс валидатора:
/** * Created by olegpro.ru * User: Oleg Maksimenko * Date: 05.12.2014 3:08 */ namespace Olegpro; use \Bitrix\Main\EventManager; class FormValidatorStringEmpty { function getDescription() { return array( 'NAME' => 'empty_string', // идентификатор 'DESCRIPTION' => 'Пустая строка', // наименование 'TYPES' => array('text'), // типы полей 'SETTINGS' => array(__CLASS__, 'getSettings'), // метод, возвращающий массив настроек 'CONVERT_TO_DB' => array(__CLASS__, 'toDB'), // метод, конвертирующий массив настроек в строку 'CONVERT_FROM_DB' => array(__CLASS__, 'fromDB'), // метод, конвертирующий строку настроек в массив 'HANDLER' => array(__CLASS__, 'doValidate') // валидатор ); } function getSettings() { return array(); } function toDB($arParams) { // возвращаем сериализованную строку return serialize($arParams); } function fromDB($strParams) { // никаких преобразований не требуется, просто вернем десериализованный массив return unserialize($strParams); } function doValidate($arParams, $arQuestion, $arAnswers, $arValues) { global $APPLICATION; foreach ($arValues as $value) { // проверяем на пустоту if (strlen(trim($value)) > 0) { // вернем ошибку $APPLICATION->ThrowException('Ошибка заполнения полей формы. Код ошибки [FKWF1].'); return false; } } // все значения прошли валидацию, вернем true return true; } }
Положил я его по пути: /bitrix/php_interface/handlers/form_validator_string_empty.php
Ну а подключить его нужно в файле /bitrix/php_interface/init.php
use \Bitrix\Main\EventManager; use \Bitrix\Main\Loader; EventManager::getInstance()->addEventHandlerCompatible('form', 'onFormValidatorBuildList', array('Olegpro\FormValidatorStringEmpty', 'getDescription') ); Loader::registerAutoLoadClasses(null, array( 'Olegpro\FormValidatorStringEmpty' => '/bitrix/php_interface/handlers/form_validator_string_empty.php', ));
После этого у поля на вкладке «Валидаторы» появится новый валидатор «[empty_string] Пустая строка»:
Его-то и нужно добавить к нашему полю для защиты от спама.
Последнее что осталось: скрыть это поле через CSS, чтобы пользователи его не видели.
28 комментариев
Валидатор в форме не появился(
Алексей, скриншот в заметке сделан с действующего проекта. Только что зашёл проверил — всё появляется, и, более того — работает.
Всё ли сделали внимательно как описано в заметке?
Олег, а если на Битриксе многосайтовость - может ли это быть связано с этим?
Нет, не может.
Огроменнейшее СПАСИБО!!!!!
Не пойму как нужно прописать код в /bitrix/php_interface/init.php - при попытке его вставить, сайт падает
Код помещаю в самый низ в <? указанный вами код ?>
Что я делаю не так?
Спасибо!
Если в init.php у вас уже что-то есть, то уберите "<?" и "?>" в начале и в конце моего кода.
Мммм ... странная ситуация. Из файла удалил весь код, и поставил только ваш, в виде:
<? use \Bitrix\Main\EventManager; use \Bitrix\Main\Loader; EventManager::getInstance()->addEventHandlerCompatible('form', 'onFormValidatorBuildList', array('Olegpro\FormValidatorStringEmpty', 'getDescription') ); Loader::registerAutoLoadClasses(null, array( 'Olegpro\FormValidatorStringEmpty' => '/bitrix/php_interface/handlers/form_validator_string_empty.php', )); ?>Сайт падает!
Ошибка 500
Посмотрите где вы применяли на рабочем проекте, может ошибка какая закралась?
если не обрамлять как php в виде <? тут ваш код ?> то на сайте просто как текст в шапке появляется!
Что то не так в вашем коде, спасибо!
С кодом всё так. Для интеграции нужны начальные знания PHP.
Вы тут выложили туториал, а теперь говорите про знания php, если вам говорят что не работает если даже положить голый год в файл, смысл тогда данной статьи?
С уважением!
Если не нашли смысла в этой заметке, то ничем, к сожалению, помочь не смогу.
Смысл в статье есть, вопрос в другом, что если код не работает, то смысл все статьи теряется!
Вся суть Битрикса - еб%т%сь как хотите! Сообщества нет, где можно обсудить проблемы. Техподдержка платная. Если у тебя закончился период обновления, и ты его не продлил, то автоматом вылетаешь и даже с репозитария не чего не имеешь права поставить! Финиш!
Извините Олег, к вам это конечно же отношения не имеет, но что то прикипело! Статья конечно же хорошая, очень помогла и поможет другим кто наткнется на нее. Всего хорошего и удачи вам!
Посмотрел логи, ошибки:
Fatal error: Class 'Bitrix\Main\EventManager' not found in /sait.ru/bitrix/php_interface/init.php on line 190
Подскажите что не нравится!?
Роман, похоже, у вас старый битрикс. Какой версии главный модуль?
Управление сайтом 12.0.3 - данный класс заменить другим можно или весь скрипт не подходит?
Замените последний блок кода в заметке на этот:
Спасибо, то что доктор прописал! Сайт перестал падать, но вышла незадача!
Форма которая используется у меня оказывается bitrix.main.feedback, а не веб-форма. Данного модуля вообще нет, хотя в редакции "малый бизнес" она есть. Написал в тех.поддержку, буду ждать ответа.
Олег спасибо за помощь!
Код ошибки [FKWF1] - название ошибки что-то означает?
И еще вопрос) в доках: В тексте ошибки можно использовать шаблон #FIELD_NAME# для получения названия поля, в котором произошла ошибка. FIELD_NAME выходит пустой, в чем может быть проблема?
Идентификация ошибки (для себя)
Тут уже не подскажу
спасибо
Как применить защиту к форме обратной связи, main.feedback.contacts, Битрикс старт? Спасибо.
Наверное, вы имели в виду компонент main.feedback? Если да, то штатно по большому счёту — никак.
Как вариант:
1) Скопировать компонент main.feedback в свой пространство имён
2) В файле component.php перед условием https://yadi.sk/i/BwWSMj_m3Hu9MV:
добавить вызов обработчика:
3) Добавить поле, которым будем выявлять бота, в ваш шаблон компонента
4) Ну и обработчиком это самое поле проверить. Если поле заполнено, то добавлять в массив $arResult['ERROR_MESSAGE'] ошибку.
Код обработчика будет примерно такой:
а ничего, что класс в инит.пхп включаю? Там ведь потом накопиться всего и будет каша. Есть иной способ подключить класс валидатора?
Можно. Есть несколько вариантов.
Самый простой — выполнить в командной php-строке в битриксе примерно следующее:
Валидатор появился, но есть проблема с самим полем. Форма отправляется независимо от его заполненности.
Огромное спасибо! Решение работает, давно такое искал!