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

Backend2026-11-09TryQuickToolBox

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

Что такое вебхуки?

Вебхук — это HTTP-колбэк: вместо того чтобы ваше приложение опрашивало API на предмет обновлений, сервис отправляет HTTP POST-запрос на указанный вами URL всякий раз, когда происходит событие. Такая модель push снижает задержку и нагрузку на сервер. Однако, поскольку запрос исходит от внешнего сервиса, вы должны рассматривать его как недоверенный ввод.

Зачем подписывать данные?

Без проверки любой, кто обнаружит вашу конечную точку вебхука, может отправлять поддельные события, потенциально вызывая несанкционированные действия. Подпись данных общим секретом позволяет подтвердить личность отправителя и убедиться, что данные не были изменены. Наиболее распространённый метод — HMAC (код аутентификации сообщения на основе хеша) с использованием SHA-256.

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

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

// Node.js example: verifying a webhook signature
const crypto = require('crypto');

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

Важно: Всегда используйте функцию сравнения с постоянным временем (например, timingSafeEqual), чтобы избежать утечки информации через различия во времени выполнения. Кроме того, вычисляйте HMAC по исходному телу, а не по распарсенному JSON, поскольку повторная сериализация может изменить последовательность байтов.

Реализация повторов

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

Стратегия повторов с точки зрения отправителя

Проектирование идемпотентного приёмника

Поскольку повторы могут приводить к дублирующимся доставкам, ваш приёмник должен обрабатывать одно и то же событие несколько раз без негативных последствий. Включите уникальный идентификатор события в данные (или заголовок) и сохраняйте обработанные ID. Если идентификатор события уже был обработан, немедленно верните 200 OK без повторной обработки.

// Pseudocode for idempotent webhook handling
function handleWebhook(event) {
  if (processedEvents.has(event.id)) {
    return { status: 200, body: 'Already processed' };
  }
  // Process event...
  processedEvents.add(event.id);
  return { status: 200, body: 'Success' };
}

Лучшие практики безопасности и надёжности вебхуков

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

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

FAQ

Как проверить подпись вебхука?

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

Что должна возвращать моя конечная точка вебхука?

Возвращайте код состояния 2xx (например, 200 OK), как только получили событие. Если вы вернёте 4xx или 5xx, отправитель может повторить попытку или пометить доставку как неудачную.

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

Это не рекомендуется. Без подписей вы не можете проверить отправителя, что делает вашу конечную точку уязвимой для поддельных запросов. Всегда используйте подписи в продакшене.

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