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

Backend2026-10-21TryQuickToolBox

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

Почему вебхукам нужны подписи

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

Как работают подписанные данные

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

Пошагово: подписание данных

  1. Создайте данные: Сериализуйте данные события в JSON. Убедитесь в единообразии форматирования (например, без лишних пробелов), поскольку подпись вычисляется по точным байтам.
  2. Добавьте временную метку: Включите временную метку Unix в данные или заголовок, чтобы предотвратить атаки повторного воспроизведения. Получатель может отклонять запросы старше нескольких минут.
  3. Вычислите HMAC: Используйте свой секретный ключ для генерации HMAC-SHA256 от строки данных (или временной метки + данных).
  4. Прикрепите подпись: Отправьте ее в заголовке, например X-Signature.

Пример на Python:

import hmac
import hashlib
import json
import time

secret = b'your_shared_secret'
payload = {"event": "user.created", "data": {"id": 123}}
body = json.dumps(payload, separators=(',', ':'))
timestamp = str(int(time.time()))
signed_content = timestamp + '.' + body
signature = hmac.new(secret, signed_content.encode(), hashlib.sha256).hexdigest()

# Отправьте заголовки: X-Signature: signature, X-Timestamp: timestamp

Проверка подписи

На принимающей стороне вы должны:

Пример проверки на Node.js:

const crypto = require('crypto');

function verifySignature(req, secret) {
  const signature = req.headers['x-signature'];
  const timestamp = req.headers['x-timestamp'];
  if (!signature || !timestamp) return false;
  if (Date.now() / 1000 - timestamp > 300) return false; // 5 мин
  const body = JSON.stringify(req.body);
  const signed = timestamp + '.' + body;
  const expected = crypto.createHmac('sha256', secret).update(signed).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Разработка стратегий повторных попыток

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

Ключевые соображения

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

Большинство отправителей вебхуков используют систему очередей (например, Redis, RabbitMQ или базу данных) для планирования повторных попыток. Вот упрощенный поток:

  1. При срабатывании события поставьте в очередь задание вебхука с данными и целевым URL.
  2. Рабочий процесс берет задание и пытается доставить.
  3. Если статус ответа 2xx, пометьте как успешное.
  4. Если нет, запланируйте повторную попытку с экспоненциальной задержкой, до максимального количества попыток.
  5. После максимального количества попыток пометьте как неудачное и уведомите.

Пример расписания повторных попыток:

ПопыткаЗадержка
1Немедленно
21 минута
35 минут
430 минут
52 часа

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

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

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

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

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

Нет универсального ответа, но распространенный подход — 3–5 повторных попыток с экспоненциальной задержкой. Учитывайте критичность события и возможности получателя.

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

Да, JWT можно использовать, но это сложнее. HMAC проще и достаточно для большинства случаев. JWT полезен, если вам нужно включить утверждения или срок действия в саму подпись.

Готовы протестировать данные вашего вебхука? Используйте наш JSON Formatter для проверки и форматирования ваших JSON-данных перед отправкой.