For the complete documentation index, see llms.txt. This page is also available as Markdown.

Капча

Как форма спрашивает проверочный код и как выбрать капчу для сайта

Гостевая книга, регистрация, форма обратной связи, вход после нескольких неудачных попыток — везде, где форма открыта для незарегистрированных, её кто-нибудь рано или поздно начнёт заполнять скриптом. Между формой и этой проверкой стоит один объект — Johncms\Captcha\CaptchaManager.

Какая именно капча стоит на сайте — настройка, а не код. Картинка с кодом, которую CMS рисует сама, hCaptcha, Yandex SmartCaptcha, Google reCAPTCHA v3 или провайдер, который принёс с собой сторонний модуль — форма во всех случаях написана одинаково.

Главное правило

Спрашивайте CaptchaManager, а не конкретную капчу.

Не создавайте Mobicms\Captcha\Image в контроллере, не читайте код из сессии руками и не пишите в форме name="code". Всё это привязывает форму к одной капче, и сайт, который переключится на SmartCaptcha, получит форму, которая молча перестанет проверять что бы то ни было.

Тот же приём, что у хранилища файлов и санитайзера HTML: вызывающий код говорит, что ему нужно, а чем это сделано — настройка и деталь реализации.

Что есть в комплекте

Ключ
Что это

image

картинка с кодом, которую рисует сама CMS. Ничего не требует и работает без интернета

hcaptcha

флажок «я не робот», с головоломкой для подозрительных посетителей

smartcaptcha

Yandex SmartCaptcha. То же самое; ключи у неё называются клиентским и серверным

recaptcha_v3

Google reCAPTCHA v3: посетитель ничего не видит, сервис возвращает оценку

Ни одному из трёх сервисов не нужен дополнительный пакет — это токен, один HTTP-запрос и тег <script>. Включаются они вводом ключей в админке.

Настройка

Админка: Система → Капча (/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

у провайдера нет ключей

Различать их важно: недоступный сервис — не ошибка посетителя, и в журнале это тоже должно выглядеть по-разному.

Дальше

Последнее обновление

Это было полезно?