Tutorials

Кеширование CAPTCHA-токенов в собственном backend в пределах TTL

Безопасный scope: это руководство применимо только к собственным или явно авторизованным QA-, staging- и production-средам. Ниже описаны диагностика, тестирование и наблюдаемость вашей собственной CAPTCHA-интеграции — не сторонние сайты и не несанкционированные workflow.

Каждый повторный вызов in.php при ретрае — это не только лишняя задержка, но и впустую занятый поток тарифа. Если запрос идемпотентен, а токен, полученный на предыдущей попытке, ещё не истёк по TTL, backend может отдать уже готовый токен вместо того, чтобы решать CAPTCHA заново. Ниже — когда это безопасно, как хранить токен в кеше и как связать это с идемпотентными ретраями.

Когда переиспользование токена оправдано

Кешировать и отдавать один и тот же токен повторно имеет смысл, когда:

  • запрос идемпотентен — это тот же самый вызов, повторённый из-за таймаута или разрыва соединения, а не новое действие пользователя;
  • сработал кратковременный сетевой сбой и backend делает retry на транспортном уровне;
  • запись транзакционна, и слой ретраев на backend уже гарантирует, что один и тот же токен не попадёт в два разных заказа.

Переиспользование недопустимо между разными пользователями, разными действиями и разными формами — токен привязан к конкретному запросу, и это единственный безопасный контекст для повторной отправки.

На практике ретраи чаще всего возникают не из-за багов в коде, а из-за нестабильной мобильной сети у конечного пользователя — типичная ситуация для мобильного трафика в регионах СНГ и Центральной Азии. Правильный TTL-кеш превращает такой повтор запроса в дешёвую операцию, а не в новый вызов API.

TTL токенов по типам CAPTCHA

Тип CAPTCHA Типичный TTL Особенность
reCAPTCHA v2 около 120 с один токен — одно действие
reCAPTCHA v3 около 120 с имя action привязано к токену
Cloudflare Turnstile до 5 мин токен одноразовый после проверки
hCaptcha около 120 с токен одноразовый

TTL задаёт провайдер CAPTCHA, а не CaptchaAI, и точные значения стоит перепроверять в его актуальной документации — они периодически меняются. В кеше всегда закладывайте запас в 10–20 секунд от заявленного TTL, чтобы не отдать токен, который истечёт по дороге к проверяющему серверу.

Минимальный кеш в собственном backend

Для одного инстанса достаточно словаря с временем истечения на каждый ключ:

import time

_cache = {}
TTL = 110

def remember(key: str, token: str) -> None:
    _cache[key] = (token, time.time() + TTL)

def get(key: str) -> str | None:
    item = _cache.get(key)
    if not item:
        return None
    token, expires = item
    if time.time() >= expires:
        _cache.pop(key, None)
        return None
    return token

Ключом кеша должен быть идентификатор конкретного запроса (sitekey + pageurl + идентификатор попытки), а не сам токен — иначе повторный поиск по кешу не сработает.

Idempotency-Key против двойного списания потока

Передавайте заголовок Idempotency-Key вместе с токеном при отправке формы на собственный backend. Если backend получает тот же ключ повторно, он возвращает результат уже проверенного токена и не запрашивает у CaptchaAI новое решение. Это защищает от двух проблем сразу: от повторного списания потока тарифа и от гонки, когда два одинаковых ретрая независимо проходят проверку и создают два заказа вместо одного.

Экономия ощутимее всего на высоконагруженных пайплайнах: на тарифе BASIC ($15/мес, 5 потоков) один лишний ретрай — это заметная доля ёмкости, а на ADVANCE ($90/мес, 50 потоков) устойчивый поток дублирующихся ретраев без Idempotency-Key может тихо съедать несколько потоков впустую.

Логи и наблюдаемость

Структурированные логи помогают сравнивать поведение CAPTCHA между релизами и быстро находить регрессии в собственных формах:

import json, time, logging

log = logging.getLogger('captcha-qa')

def record(event: str, **fields) -> None:
    payload = {'ts': time.time(), 'event': event, **fields}
    log.info(json.dumps(payload, ensure_ascii=False))

Минимальный набор полей на каждую попытку: slug, captcha_type, task_id, wait_seconds, verify_status, env. Этого достаточно, чтобы построить дашборд медианы, P90 и P99 по типу CAPTCHA и по среде. Если в тестовые сценарии попадают данные реальных пользователей, помните про требования 152-ФЗ (или аналогичные требования вашей юрисдикции) — логируйте только данные фиктивных тестовых аккаунтов, помеченных как такие.

Типичные проблемы

Симптом Что сделать
Токен невалиден на ретрае Уменьшите TTL в кеше, добавьте запас
Двойные списания у клиента Проверьте, что Idempotency-Key действительно уникален на запрос
Кеш растёт неограниченно Включите периодическую очистку по expiry
После рестарта кеш пуст Перейдите на Redis с TTL вместо памяти процесса

Чек-лист перед деплоем

  • Запросы уходят только на собственные или авторизованные endpoints.
  • Тестовые учётные записи, события и платежи явно помечены как фиктивные.
  • CAPTCHA-токен проверяется на собственном backend, а не принимается со слов клиента.
  • Логи содержат task_id, тип CAPTCHA, время ожидания и итоговый статус.
  • Скрипт возвращает корректный exit code, чтобы CI мог принять решение по сборке.

Частые вопросы

Сколько живёт токен Cloudflare Turnstile в кеше?

До 5 минут по заявленному TTL, но закладывайте запас: храните токен в кеше на 4–4,5 минуты, а не на полный срок, чтобы исключить гонку между истечением и проверкой на стороне сервера.

Как избежать двойного списания потока при ретрае?

Свяжите каждый исходный запрос с Idempotency-Key и проверяйте его на backend перед тем, как обращаться к CaptchaAI заново. Если ключ уже встречался и токен ещё валиден по TTL, отдавайте сохранённый результат.

Нужен ли Redis, если TTL токена — всего пара минут?

Для одного инстанса достаточно памяти процесса. Redis становится нужен, как только сервисов или воркеров больше одного — иначе рестарт или деплой одного инстанса обнуляет кеш, и соседний инстанс не увидит уже решённый токен.

Что делать, если CaptchaAI вернул ошибку при повторном решении?

Логируйте task_id, тип CAPTCHA и текст ошибки, повторите запрос с экспоненциальной задержкой и фиксируйте долю ошибок в дашборде. Устойчивый рост ошибок — повод проверить sitekey и целевую страницу, а не сразу увеличивать таймаут.

Можно ли использовать этот подход на сторонних сайтах?

Нет. Кеш и повторное использование токена применимы только к собственным или явно авторизованным средам. Для чужих ресурсов нужно письменное разрешение владельца сайта.

Безопасные связанные руководства

Настройте TTL-кеш и Idempotency-Key для своего backend — подключите CaptchaAI.

Комментарии для этой статьи отключены.