ЛОДЖИК ТЕЛЕКОМ
Коммуникации3 августа 2026 г.6 мин

OTP-коды через SMS: TTL, повторы и защита от фрода

Как спроектировать отправку одноразовых кодов через SMS: срок действия, лимиты попыток, идемпотентность, повторные отправки, DLR и резервные каналы.

Защищённая передача одноразового кода через SMS-шлюз
Содержание

SMS с одноразовым кодом — только транспорт. Безопасность сценария определяют серверная проверка, короткий срок действия кода, ограничения на запросы и попытки ввода, защита журналов и понятное поведение при задержке доставки. Если эти элементы не согласованы, даже стабильно работающий SMS-шлюз не защитит вход или подтверждение операции.

Из каких компонентов состоит OTP-сценарий

Надёжный процесс лучше разделить на четыре независимых слоя:

  1. бизнес-сервис создаёт запрос на подтверждение конкретного действия;
  2. сервис аутентификации выпускает одноразовый код и хранит его проверочное представление;
  3. коммуникационная платформа передаёт сообщение оператору и возвращает идентификатор отправки;
  4. сервис аутентификации принимает код, проверяет срок действия, число попыток и связь с исходным действием.

Код нельзя считать самостоятельным доказательством личности. Его следует связывать с идентификатором операции, пользователем или сессией, а для чувствительных действий — дополнять оценкой риска и другими факторами.

TTL: сколько должен жить код

Срок действия должен быть достаточно длинным для обычной сетевой задержки, но не превращать код в долгоживущий пароль. Универсального числа нет: его выбирают по сценарию, измеренной задержке доставки и уровню риска. Вход в кабинет, подтверждение платежа и изменение контактных данных требуют разных правил.

Сервер обязан проверять время выпуска, а не доверять таймеру в интерфейсе. После успешного подтверждения код немедленно становится недействительным. Новый код обычно должен аннулировать предыдущий для той же операции, иначе пользователь может получить несколько сообщений и случайно применить устаревшее значение.

Практическое правило: сначала измерьте P95 и P99 времени доставки на рабочем трафике, затем задайте TTL с контролируемым запасом. Если редкие задержки постоянно выходят за окно, нужно улучшать маршрут или резервный сценарий, а не бесконечно увеличивать срок жизни кода.

Повторная отправка без дублей

Кнопка «Отправить ещё раз» создаёт сразу три риска: лишние расходы, несколько действующих кодов и возможность массово отправлять сообщения на чужой номер. Поэтому повтор должен проходить через серверные ограничения.

  • Установите минимальный интервал между запросами.
  • Ограничьте число отправок на номер, учётную запись, сессию и сетевой источник.
  • Используйте идентификатор запроса и идемпотентность, чтобы повтор HTTP-запроса не создавал новое SMS.
  • Не запускайте вторую отправку только потому, что DLR ещё не пришёл: статус доставки может задерживаться.
  • После достижения лимита переводите пользователя в безопасный альтернативный процесс, а не сообщайте точную причину блокировки злоумышленнику.

Если используется резервный провайдер или канал, оркестратор должен хранить единый статус операции. Иначе два независимых маршрута могут доставить разные коды почти одновременно.

Лимиты проверки и защита от перебора

Длина кода сама по себе не заменяет контроль попыток. Сервер ограничивает количество неверных вводов для конкретного OTP-запроса и применяет более широкие лимиты к пользователю, номеру и источнику запросов. После исчерпания попыток код блокируется, даже если его TTL ещё не закончился.

Код не следует хранить или писать в журналы открытым текстом. Для проверки достаточно защищённого производного значения и серверного секрета. Доступ к журналам, очередям и трассировкам ограничивают, а номер телефона маскируют там, где полное значение не нужно для эксплуатации.

Особенно важно не раскрывать через ответы API, зарегистрирован ли номер в системе. Одинаковые внешние сообщения и сопоставимое время ответа уменьшают риск перебора существующих учётных записей.

Какие статусы нужны от SMS-платформы

Интеграции недостаточно ответа «запрос принят». Для эксплуатации нужны как минимум:

  • внутренний идентификатор OTP-запроса;
  • идентификатор сообщения у коммуникационной платформы;
  • время создания, принятия платформой, передачи оператору и получения финального DLR;
  • нормализованный статус и исходный код ошибки;
  • маршрут или группа маршрутов без раскрытия чувствительных данных;
  • признак повтора и выбранного резервного канала.

Принятое платформой сообщение ещё не доставлено на устройство. Подробнее о различиях между статусами и показателях качества — в руководстве по метрикам доставки SMS.

Когда включать резервный канал

Резервирование полезно только при заранее определённых условиях. Например, если сообщение не было принято оператором, можно выбрать другой SMS-маршрут; если срок подтверждения почти закончился, пользователю можно предложить голосовой вызов, push или подтверждение внутри приложения. Автоматическая повторная отправка во все каналы сразу создаёт дубли и ухудшает пользовательский опыт.

Резервный канал не должен обходить правила безопасности основного. Он использует тот же идентификатор операции, общий лимит попыток и единое решение о том, действителен ли код. Для операций высокого риска доступность канала не должна автоматически снижать требования к подтверждению.

Схема API-интеграции

Минимальный контракт удобно строить вокруг ресурса подтверждения, а не вокруг отдельного SMS:

  1. POST /verifications создаёт операцию и возвращает непрозрачный verification_id;
  2. сервис асинхронно отправляет уведомление через QuickTel или другую коммуникационную платформу;
  3. webhook обновляет транспортные статусы, но не принимает решение об успешной аутентификации;
  4. POST /verifications/{id}/check проверяет код и атомарно закрывает операцию;
  5. повторная отправка создаётся отдельной командой с ключом идемпотентности и общими лимитами.

Секреты API хранят вне кода, запросы к webhook проверяют, а повторную доставку событий обрабатывают идемпотентно. Общие варианты подключения разобраны в сравнении SMPP и HTTP API.

Метрики, которые показывают качество сценария

Одной доли доставленных SMS недостаточно. Команда должна видеть:

  • долю кодов, доставленных внутри целевого окна;
  • P50, P95 и P99 времени от запроса до DLR;
  • конверсию из запроса OTP в успешное подтверждение;
  • долю повторных отправок и резервных каналов;
  • число неверных попыток, блокировок и запросов сверх лимита;
  • расхождение между доставкой сообщения и успешным вводом кода;
  • ошибки по операторам, маршрутам, регионам и шаблонам.

Резкий рост повторов при стабильном DLR может указывать на задержку сообщения, непонятный интерфейс или проблемы с шаблоном. Высокая доставка при низкой конверсии требует проверки всего пользовательского пути, а не только SMS-провайдера.

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

  • Код связан с конкретной операцией и одноразово закрывается.
  • TTL и лимиты задаются на сервере.
  • Новый код аннулирует предыдущий по определённому правилу.
  • Есть ограничения по номеру, пользователю, сессии и источнику.
  • Код и полный номер не попадают в обычные журналы.
  • Повторы API не создают дубли благодаря идемпотентности.
  • DLR не используется как единственное доказательство личности.
  • Резервный канал разделяет общие лимиты и статус операции.
  • Алерты учитывают задержку, конверсию и признаки злоупотребления.
  • Команда регулярно тестирует задержки, недоступность маршрута и повтор webhook.

Практический вывод

Безопасный OTP через SMS начинается не с текста сообщения, а с модели состояния: одна операция, ограниченный срок, ограниченное число попыток и наблюдаемый путь доставки. QuickTel может быть транспортным и интеграционным слоем для корпоративных SMS, однако правила выпуска и проверки кода остаются ответственностью бизнес-системы.

Перед промышленным запуском согласуйте нагрузку, требуемую пропускную способность, маршрутизацию, webhook и резервирование. Для критичных операций проведите отдельное моделирование угроз и не используйте SMS как единственный защитный механизм.

SMSA2PИнтеграцииБезопасность

Читайте также