Вебхуки: приём, подпись, повторы, идемпотентность

↑ 5.5 Интеграции со сторонними API: 1С, Битрикс24, FHIR · ← Предыдущая · → Следующая

По желанию~3 мин чтенияУровень: middle

Зачем это на собесе

Вопрос «как безопасно принять вебхук от платёжной системы» проверяет и безопасность, и надёжность.

Объяснение

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

ТребованиеКак
Аутентичностьпроверка HMAC-подписи заголовка по секрету (X-Signature) над сырым телом
Защита от replayметка времени в подписи, окно 5 минут
Быстрый ответпринять, положить в очередь/БД, вернуть 2xx за секунды; обработка асинхронно
Идемпотентностьдедупликация по event_id
Повторы отправителяпровайдер повторяет при не-2xx: обрабатывайте дубли
Порядоксобытия могут прийти не по порядку: сверяйтесь с версией/временем или перезапрашивайте состояние
Наблюдаемостьлог событий, метрики, DLQ
app.MapPost("/webhooks/acme", async (HttpRequest req, IWebhookQueue queue, IOptions<AcmeOptions> o) =>
{
    using var ms = new MemoryStream();
    await req.Body.CopyToAsync(ms);
    var body = ms.ToArray();
 
    var expected = Convert.ToHexString(HMACSHA256.HashData(Encoding.UTF8.GetBytes(o.Value.Secret), body));
    if (!CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(expected.ToLower()),
                                                 Encoding.UTF8.GetBytes(req.Headers["X-Signature"].ToString())))
        return Results.Unauthorized();
 
    await queue.EnqueueAsync(body);          // сохранить и подтвердить
    return Results.Ok();
});

Нюансы и подводные камни

  • Подпись считается по байтам тела: не пересериализуйте JSON до проверки.
  • Сравнение подписи — за постоянное время.
  • Долгая обработка в обработчике → таймаут у отправителя → лавина повторов.
  • Не доверяйте содержимому: после события запросите актуальное состояние через API.
  • Ограничьте размер тела и IP-адреса отправителя, если провайдер их публикует.

Практика

  1. Реализуйте приём вебхука с проверкой HMAC и защитой от replay.
  2. Сымитируйте повторную доставку и убедитесь в идемпотентности.
  3. Настройте DLQ для событий, которые не удалось обработать.

Вопросы с ответами

Связанные темы