Вебхуки: подписанные payload'ы и стратегии повторов

Backend2026-10-19TryQuickToolBox

Вы только что интегрировали сторонний сервис, который отправляет вебхуки, и в тестах всё работает отлично. Но в продакшене вы замечаете случайные пропущенные события, дублирующиеся доставки или, что хуже, злоумышленника, отправляющего поддельные payload'ы на ваш эндпоинт. Вебхуки просты в концепции, но сложны на практике. В этой статье объясняется, как защитить вебхуки с помощью подписанных payload'ов и реализовать надёжные стратегии повторных попыток, чтобы вы могли доверять своим интеграциям, управляемым событиями.

Что такое вебхуки и почему они важны

Вебхуки — это определяемые пользователем HTTP-колбэки, запускаемые определёнными событиями. Когда происходит событие — например, успешный платёж или регистрация нового пользователя — исходный сервис отправляет HTTP POST-запрос на указанный вами URL. Эта модель на основе push эффективнее опроса (polling), снижая задержку и нагрузку на сервер. Однако она создаёт проблемы: проверка подлинности и обработка сбоев доставки.

Защита вебхуков с помощью подписанных payload'ов

Без проверки любой может отправлять запросы на ваш эндпоинт вебхука. Подписанные payload'ы решают эту проблему, включая криптографическую подпись, которая подтверждает, что запрос исходит от доверенного отправителя.

Как работают HMAC-подписи

Большинство провайдеров используют HMAC (код аутентификации сообщений на основе хэша) с общим секретом. Отправитель вычисляет хэш payload'а с использованием секрета и включает его в заголовок (например, X-Signature). Ваш сервер пересчитывает хэш и сравнивает. Если они совпадают, запрос подлинный.

// Пример: Проверка подписи вебхука в Node.js
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const digest = hmac.digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}

Важно: Всегда используйте сравнение, устойчивое к атакам по времени, чтобы предотвратить timing-атаки. Также проверяйте подпись по исходному телу запроса, а не по распарсенному JSON-объекту, поскольку парсинг может изменить payload.

Лучшие практики проверки подписи

Реализация надёжных повторных попыток

Даже с подписанными payload'ами сетевые проблемы или временные сбои могут привести к неудачной доставке вебхука. Надёжная стратегия повторных попыток гарантирует, что события в конечном итоге будут доставлены, не перегружая вашу систему.

Экспоненциальная задержка с джиттером

Немедленный повтор может усугубить перегрузку. Вместо этого используйте экспоненциальную задержку: увеличивайте время ожидания между каждой попыткой. Добавьте джиттер (случайное отклонение), чтобы избежать проблемы «громового стада», когда многие вебхуки терпят неудачу одновременно.

// Пример: Расписание повторов с экспоненциальной задержкой и джиттером
function getRetryDelay(attempt) {
  const base = 1000; // 1 секунда
  const max = 30000; // 30 секунд
  const delay = Math.min(base * Math.pow(2, attempt), max);
  return delay + Math.random() * 1000; // добавить до 1с джиттера
}

Идемпотентность: обработка дубликатов

Повторные попытки могут вызвать дублирующиеся доставки. Ваш обработчик вебхуков должен быть идемпотентным — обработка одного и того же события несколько раз должна иметь тот же эффект, что и однократная обработка. Используйте ID события из payload'а для отслеживания обработанных событий.

Быстро отвечайте и подтверждайте

Ваш эндпоинт вебхука должен отвечать кодом состояния 2xx как можно быстрее — в идеале в течение нескольких секунд. Если обработка занимает больше времени, поставьте событие в очередь для асинхронной обработки и верните 202 Accepted. Это предотвращает тайм-ауты и ненужные повторные попытки.

Сравнение: вебхуки против опроса

Аспект Вебхуки Опрос
Задержка Почти в реальном времени Зависит от интервала
Нагрузка на сервер Низкая (только push) Высокая (постоянные запросы)
Сложность Выше (нужны повторы, безопасность) Ниже
Надёжность Требует логики повторов По своей сути надёжна

Пошагово: создание безопасного получателя вебхуков

  1. Настройте HTTPS-эндпоинт с действующим сертификатом.
  2. Извлеките заголовок подписи (например, X-Signature) и метку времени.
  3. Проверьте подпись с использованием общего секрета и исходного тела.
  4. Проверьте метку времени, чтобы отклонить старые запросы (например, старше 5 минут).
  5. Разберите payload и проверьте наличие дублирующихся ID событий.
  6. Обработайте событие асинхронно при необходимости и ответьте 200 OK.
  7. Залогируйте событие для аудита и отладки.

Часто задаваемые вопросы

Что такое подписанный payload вебхука?

Подписанный payload включает криптографическую подпись (обычно HMAC), которая позволяет получателю проверить, что запрос пришёл из доверенного источника и не был изменён.

Сколько раз следует повторять неудачный вебхук?

Большинство систем повторяют 3–5 раз с экспоненциальной задержкой. После этого событие обычно помечается как неудачное и может потребовать ручного вмешательства или обработки через очередь недоставленных сообщений (dead-letter queue).

Можно ли использовать вебхуки без HTTPS?

Это настоятельно не рекомендуется. Без HTTPS payload'ы и подписи могут быть перехвачены или изменены. Всегда используйте TLS для эндпоинтов вебхуков.

При отладке payload'ов вебхуков или логов правильное форматирование JSON имеет решающее значение. Используйте наш JSON Formatter для быстрого форматирования и проверки JSON-payload'ов.