Капча
Как форма спрашивает проверочный код и как выбрать капчу для сайта
Гостевая книга, регистрация, форма обратной связи, вход после нескольких неудачных попыток — везде, где форма открыта для незарегистрированных, её кто-нибудь рано или поздно начнёт заполнять скриптом. Между формой и этой проверкой стоит один объект — Johncms\Captcha\CaptchaManager.
Какая именно капча стоит на сайте — настройка, а не код. Картинка с кодом, которую CMS рисует сама, hCaptcha, Yandex SmartCaptcha, Google reCAPTCHA v3 или провайдер, который принёс с собой сторонний модуль — форма во всех случаях написана одинаково.
Главное правило
Спрашивайте CaptchaManager, а не конкретную капчу.
Не создавайте Mobicms\Captcha\Image в контроллере, не читайте код из сессии руками и не пишите в форме name="code". Всё это привязывает форму к одной капче, и сайт, который переключится на SmartCaptcha, получит форму, которая молча перестанет проверять что бы то ни было.
Что есть в комплекте
image
картинка с кодом, которую рисует сама CMS. Ничего не требует и работает без интернета
hcaptcha
флажок «я не робот», с головоломкой для подозрительных посетителей
smartcaptcha
Yandex SmartCaptcha. То же самое; ключи у неё называются клиентским и серверным
recaptcha_v3
Google reCAPTCHA v3: посетитель ничего не видит, сервис возвращает оценку
Ни одному из трёх сервисов не нужен дополнительный пакет — это токен, один HTTP-запрос и тег <script>. Включаются они вводом ключей в админке.
reCAPTCHA v3 не показывает посетителю ничего и не даёт ему шанса доказать, что он человек: тот, чья оценка ниже порога, просто получает отказ. Кроме того, она подгружает скрипты Google на каждую страницу с формой — это решение не только про спам, но и про посетителей сайта. Если нужен видимый флажок, берите hCaptcha или SmartCaptcha.
Настройка
Админка: Система → Капча (/admin/settings/captcha). На странице перечислены все провайдеры, которые есть в системе, у каждого — свои поля. Переключатель слева от названия выбирает тот, который будут показывать формы.
Настройки сохраняются в config/autoload/captcha.local.php — то есть в ту половину конфигурации, которая не лежит в репозитории. Ключи сервисов туда и должны попадать, рядом с паролем от базы. Значения по умолчанию — в captcha.global.php.
Провайдер без ключей не показывают посетителям. Если выбранный сервис не настроен или его вообще никто не регистрирует (модуль удалили, в конфиге опечатка), формы вернутся к встроенной картинке. Капча, которая не может работать, не должна незаметно превращаться в отсутствие капчи.
Капча в своей форме
1. Контроллер: попросить задание
challenge() возвращает CaptchaChallenge — всё, что нужно шаблону: имя шаблона виджета, имя поля и его параметры (картинка, публичный ключ). Что именно там окажется, зависит от выбранного провайдера, и знать это форме не нужно.
Если капча нужна не всем — например, только гостям, — передавайте null и проверяйте в шаблоне:
2. Шаблон: один компонент
Компонент сам подключит шаблон нужного виджета. Своей разметки — <img src="..."> и поля ввода — в форме быть не должно.
3. Чтение ответа: по имени от провайдера
Имя поля у каждой капчи своё: у встроенной — code, у reCAPTCHA — g-recaptcha-response, у SmartCaptcha — smart-token. Поэтому имя не пишут руками:
Ключ массива (code) — ваш, по нему потом придёт сообщение об ошибке. Из запроса читают по fieldName().
4. Правило валидации
Правило само сходит к активному провайдеру. Подробности — в разделе правил валидации.
Области (scope)
Область — это имя формы, которую защищает капча: login, registration, guestbook, contacts. Она нужна, чтобы две формы, открытые в двух вкладках, не затирали ответы друг друга: раньше все они держали код под одним ключом сессии, и открытая форма регистрации ломала проверку на странице входа.
Правило простое: область, с которой выдали задание, и область, с которой его проверяют, должны совпадать. Поэтому её выносят в константу той формы, которой она принадлежит, а не пишут строкой в двух местах.
Ответ действует один раз
Проверка тратит ответ: одну и ту же картинку нельзя ответить дважды, а перехваченную отправку формы нельзя повторять, пока не пройдёт. Из этого следует одно практическое требование: задание выдают после валидации, чтобы форма, показанная снова из-за ошибки, несла новое:
Ничего чистить в сессии после проверки не нужно.
Почему проверка не прошла
Провайдер отвечает не «да/нет», а CaptchaResult с причиной, и посетитель видит разный текст:
Missing
ничего не отправлено
Mismatch
ответ неверный
Expired
задание устарело: обновилась сессия, токен уже использован или просрочен
LowScore
сервис счёл посетителя ботом, не дав ему ничего решить (reCAPTCHA v3)
Unavailable
сервис не ответил или отказал
NotConfigured
у провайдера нет ключей
Различать их важно: недоступный сервис — не ошибка посетителя, и в журнале это тоже должно выглядеть по-разному.
Дальше
Свой провайдер капчи — как добавить ещё одну капчу из модуля.
Последнее обновление
Это было полезно?