Проблема спама через формы и почему Turnstile лучше reCAPTCHA
Спам через веб-формы — одна из самых распространённых проблем для владельцев сайтов. Боты автоматически заполняют формы обратной связи, регистрации и оформления заказов, засоряя базу данных мусорными заявками и создавая нагрузку на сервер. Классические решения вроде Google reCAPTCHA v2 раздражают пользователей заданиями «выберите все светофоры», а reCAPTCHA v3 работает непрозрачно и нередко блокирует реальных посетителей.
Cloudflare Turnstile — современная альтернатива, которая решает эти проблемы кардинально. Сервис появился в 2022 году и быстро завоевал популярность среди разработчиков. В этой статье разберём, как интегрировать Turnstile в форму на сайте с полной серверной проверкой.
Что такое Cloudflare Turnstile
Cloudflare Turnstile — это CAPTCHA-решение нового поколения от компании Cloudflare. В отличие от традиционных капч, Turnstile работает незаметно для пользователя: он анализирует поведенческие сигналы браузера, репутацию IP-адреса и другие факторы без явного взаимодействия с посетителем. В большинстве случаев пользователь видит только зелёную галочку — без загадок и пазлов.
Ключевые преимущества Cloudflare Turnstile перед конкурентами:
- Конфиденциальность — не передаёт данные пользователей третьим сторонам в рекламных целях (в отличие от Google reCAPTCHA).
- Удобство — в 99% случаев пользователь проходит проверку автоматически, без ручных заданий.
- Производительность — скрипт весит меньше и загружается быстрее, чем аналоги от Google.
- Бесплатно — до 1 миллиона проверок в месяц бесплатно для любого тарифного плана Cloudflare.
- Простая интеграция — понятный API, хорошая документация, поддержка явного и неявного режима рендеринга.
Предварительные требования
Для интеграции Turnstile вам потребуется:
- Аккаунт Cloudflare (бесплатный план подходит) — зарегистрируйтесь на dash.cloudflare.com.
- Доступ к коду фронтенда и бэкенда вашего сайта.
- Поддержка cURL на сервере (для серверной верификации токена).
- jQuery на фронтенде (в примере используется для AJAX-запросов).
Пошаговая инструкция по подключению
Шаг 1. Создание аккаунта и виджета в Cloudflare
Если аккаунт Cloudflare ещё не создан, зарегистрируйтесь по ссылке https://dash.cloudflare.com/. Аккаунт бесплатный и не требует привязки домена к Cloudflare.
Шаг 2. Переход в раздел Turnstile
В левом меню панели управления Cloudflare найдите раздел Turnstile. Он доступен напрямую из главного дашборда, без необходимости добавлять домен в Cloudflare DNS.
Шаг 3. Добавление домена и получение ключей
Нажмите «Add Site», введите название виджета и укажите домен вашего сайта. После сохранения Cloudflare выдаст два ключа: Site Key (публичный, для фронтенда) и Secret Key (приватный, только для сервера). Храните Secret Key в безопасном месте — никогда не передавайте его на клиент.
Шаг 4. Подключение скрипта Turnstile на страницу
Добавьте скрипт Cloudflare в раздел <head> или перед закрывающим тегом <body>. Параметр render=explicit означает, что виджет будет инициализирован вручную через JavaScript — это позволяет контролировать момент отображения капчи:
|
1 |
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script> |
Шаг 5. Добавление контейнера виджета в форму
Разместите div-контейнер внутри HTML-формы. Атрибут data-sitekey — это ваш публичный ключ из панели Cloudflare. Атрибут data-callback задаёт имя функции, которая будет вызвана после успешной проверки (в нашем примере эта логика вынесена в код промиса):
|
1 |
<div class="cf-turnstile" data-sitekey="111111111111111111" data-callback="cfCallback"></div> |
Шаг 6. Обёртка AJAX-запроса в Promise
Ключевой момент интеграции — порядок действий: сначала нужно убедиться, что пользователь прошёл проверку Turnstile, получить токен, отправить его на сервер для верификации, и только после успешного ответа — отправить основной запрос формы. Это реализуется через цепочку Promise:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
const $form = $('#myForm'); new Promise((resolve) => { const curEl = $form.find('.cf-turnstile'); if (curEl.length > 0) { turnstile.ready(function () { curEl.show(); turnstile.render(curEl[0], { callback: function (token) { $.ajax({ url: '/ajax/checkCapcha.php', type: 'post', data: {secret_token: token}, dataType: 'json', success: function (res) { res = JSON.parse(res); if (res.success) { resolve({'ok': true}); curEl.hide(); } else { alert("Error capcha validate!"); curEl.show(); } }, error: function (result) { console.log(result); } }); }, }); }); } else { resolve({'ok': true}); } }).then((result) => { if (result.ok) { $.ajax({ url: $form.action, type: $form.method, dataType: "json", data: $form.serialize(), success: function (e) { console.log(e) if (e.ok) { alert("Success!") } else { alert("This is a spam!") } t.removeClass("load"); }, error: function (e) { console.log(e); } }); } }).catch((e) => { console.log(e); console.log('promise erroe catch'); }); |
Разберём логику: функция turnstile.ready() ждёт полной загрузки скрипта Cloudflare, затем turnstile.render() инициализирует виджет в указанном контейнере. Когда пользователь успешно проходит проверку, Cloudflare вызывает callback с токеном. Этот токен отправляется на сервер через AJAX.
Шаг 7. Серверная верификация токена (PHP)
Никогда не доверяйте только клиентской проверке. Токен, полученный от Cloudflare, необходимо верифицировать на сервере, отправив запрос к API Cloudflare. Создайте файл /ajax/checkCapcha.php:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$res = [ "success" => false ]; if ( isset( $_POST['secret_token'] ) ) { $ch = curl_init(); $SECRET_KEY = 'ВАШ Secret Key'; $SECRET_TOKEN = $_POST["secret_token"]; curl_setopt($ch, CURLOPT_URL, 'https://challenges.cloudflare.com/turnstile/v0/siteverify'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "secret=$SECRET_KEY&response=$SECRET_TOKEN"); $headers = array(); $headers[] = 'Content-Type: application/x-www-form-urlencoded'; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); $res = $result; curl_close($ch); } echo json_encode($result); |
Сервер отправляет POST-запрос к эндпоинту siteverify с двумя параметрами: secret (ваш Secret Key) и response (токен от пользователя). Cloudflare возвращает JSON с полем success: true/false. Если проверка прошла — токен действителен и пользователь не бот.
Как тестировать интеграцию
Cloudflare предоставляет специальные тестовые ключи для разработки. Site Key 1x00000000000000000000AA всегда возвращает успешную проверку, а 2x00000000000000000000AB — всегда провальную. Используйте их в окружении разработки, чтобы проверить оба сценария без реальных запросов к API.
Частые ошибки и их решение
- Виджет не отображается — убедитесь, что скрипт загружается до вызова
turnstile.render(), и что контейнер.cf-turnstileсуществует в DOM в момент вызова. - Ошибка «invalid-input-secret» — проверьте Secret Key: скорее всего, вы случайно использовали Site Key вместо Secret Key на сервере.
- Токен уже использован — каждый токен Turnstile одноразовый. После успешной проверки нужно запросить новый токен при следующей отправке формы.
- cURL не может подключиться к Cloudflare — проверьте, разрешён ли исходящий HTTPS-трафик с вашего сервера. Некоторые хостинги блокируют исходящие соединения.
Заключение
Cloudflare Turnstile — практичное и бесплатное решение для защиты форм от спама. Интеграция занимает около часа и не требует специальных знаний. По сравнению с reCAPTCHA, Turnstile выигрывает по UX, конфиденциальности и простоте настройки. Полная документация доступна на официальном сайте: developers.cloudflare.com/turnstile.
