Вебхуки: подписанные данные и повторы
Вы только что интегрировали платёжный шлюз или сервис CI/CD, и теперь вам нужно получать события в реальном времени. Вебхуки — стандартное решение, но с ними связаны подводные камни: неаутентифицированные данные, потерянные события и дублирующиеся доставки. В этой статье объясняется, как работают вебхуки, как подписывать данные для предотвращения подделки и как реализовать повторы для надёжной доставки.
Что такое вебхуки?
Вебхук — это определяемый пользователем HTTP-колбэк. Вместо того чтобы ваше приложение опрашивало API на предмет обновлений, провайдер отправляет HTTP POST-запрос на указанный вами URL всякий раз, когда происходит событие. Это эффективнее и позволяет реагировать почти в реальном времени.
Типичные случаи использования:
- Уведомления о платежах (например, Stripe, PayPal)
- Статус сборки CI/CD (например, GitHub, GitLab)
- Платформы обмена сообщениями (например, Slack, Discord)
- Обновления CRM (например, Salesforce)
Зачем подписывать данные вебхуков?
Конечные точки вебхуков — это общедоступные URL. Без проверки любой может отправить поддельные данные, что приведёт к повреждению данных или нарушению безопасности. Подпись данных общим секретом обеспечивает подлинность и целостность.
Большинство провайдеров используют HMAC (код аутентификации сообщений на основе хэша) с SHA-256. Провайдер вычисляет подпись по исходному телу запроса с использованием секретного ключа и включает её в заголовок (например, X-Hub-Signature-256). Ваш сервер пересчитывает подпись и сравнивает её.
Как проверить подпись
Пошаговое руководство:
- Получите исходное тело точно в том виде, в каком оно было отправлено. Не разбирайте и не изменяйте его до проверки.
- Извлеките подпись из заголовка.
- Вычислите ожидаемую подпись с помощью HMAC-SHA256 и вашего секрета.
- Сравните с помощью функции с постоянным временем выполнения, чтобы предотвратить атаки по времени.
Пример на Node.js:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
}
На Python:
import hmac
import hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f'sha256={expected}', signature)
Всегда используйте сравнение с постоянным временем выполнения, чтобы избежать утечки информации.
Реализация повторов для надёжности
Сети дают сбои, серверы перезапускаются, происходят развёртывания. Надёжная система вебхуков должна повторять неудачные доставки. Провайдеры обычно повторяют с экспоненциальной задержкой, но вы также должны обрабатывать повторы на принимающей стороне.
Стратегии повторов
- Экспоненциальная задержка: ждать 1 с, 2 с, 4 с, 8 с и т. д. между повторами.
- Максимальное число попыток: ограничьте повторы, чтобы избежать бесконечных циклов (например, 5 попыток).
- Очередь недоставленных сообщений: после максимального числа попыток сохраните событие для ручной проверки.
- Идемпотентность: убедитесь, что обработка одного и того же события несколько раз не вызывает дублирующихся побочных эффектов.
Ключи идемпотентности
Многие провайдеры включают уникальный идентификатор события (например, X-Event-ID). Сохраняйте обработанные идентификаторы в базе данных или кэше, чтобы пропускать дубликаты. Например, используйте Redis с TTL для отслеживания увиденных идентификаторов.
Сравнение: опрос vs вебхуки
| Аспект | Опрос | Вебхуки |
|---|---|---|
| Задержка | Зависит от интервала | Почти в реальном времени |
| Нагрузка на сервер | Высокая (постоянные запросы) | Низкая (только при событиях) |
| Сложность | Просто реализовать | Требует конечной точки, безопасности, повторов |
| Надёжность | Пропускает события между опросами | Может пропустить, если конечная точка недоступна; повторы помогают |
Лучшие практики для потребителей вебхуков
- Отвечайте быстро: возвращайте 2xx в течение нескольких секунд; обрабатывайте асинхронно.
- Проверяйте подписи: всегда проверяйте перед обработкой.
- Логируйте всё: сохраняйте исходные данные и заголовки для отладки.
- Используйте HTTPS: никогда не принимайте вебхуки по обычному HTTP.
- Следите за сбоями: настройте оповещения о повторных неудачных попытках.
FAQ
Что такое подпись вебхука?
Подпись вебхука — это HMAC-хэш данных, созданный с использованием общего секрета. Она позволяет получателю убедиться, что запрос пришёл от ожидаемого отправителя и не был подделан.
Сколько раз следует повторять неудачный вебхук?
Универсального числа нет, но обычно это 3–5 повторов с экспоненциальной задержкой. После этого залогируйте событие в очередь недоставленных сообщений для ручной проверки.
Можно ли использовать вебхуки без HTTPS?
Технически да, но это крайне небезопасно. Всегда используйте HTTPS для шифрования данных и предотвращения атак типа «человек посередине».
Готовы протестировать свои конечные точки вебхуков? Используйте наш JSON Formatter, чтобы быстро просмотреть и проверить данные.