Към съдържанието

Техника · 7 ноември 2026 г. · 6 мин четене

Webhook, обяснен просто: подпис, повторение, сигурност

Какво е Webhook, с какво се различава от API заявката и как да обработвате подпис, повторение и дубликати. С curl и Node.

Два пътя в сравнение: при API заявката Вашата система пита отново и отново, при Webhook изпращачът вика Вашия адрес еднократно, щом нещо се случи
Графика: Whovisit · Преглед на графиката в голям размер

Webhook е обаждане в обратната посока. Вместо Вашата система да пита една услуга на всеки няколко минути дали нещо се е случило, услугата вика един адрес при Вас, щом се случи. Това спестява заявки и доставя новините по-бързо. За това трябва да осигурите и защитите приемник. Тази статия обяснява и двете.

Webhook или API заявка

API заявка (Polling)Webhook
Кой започва?Вашата системаИзпращачът
Кога?По график, например всеки часЩом настъпи събитие
УсилияЗаявки и без новиниНужен е достъпен приемник
Подходящ заОтчети, съпоставяне, дозарежданеИзвестяване, препращане
РискЗабавяне до следващата заявкаСъобщението се губи, ако приемникът не отговори

На практика мнозина комбинират двете: Webhook съобщава за събитието, API извлича при нужда подробностите или запълва пропуските след срив.

Как протича една доставка

  1. Настъпва събитие, например „постъпило плащане“.
  2. Изпращачът изпраща POST с JSON към вписания Ваш адрес (HTTPS).
  3. Вашият приемник проверява подписа, запомня съобщението и отговаря бързо с код от диапазона 2xx.
  4. Същинската работа Вашата система върши след това.

Стъпка 3 е важна. Stripe препоръчва в документацията за Webhook веднага да се върне код 2xx, преди да тече сложна логика, която може да предизвика изтичане на времето. Който първо осчетоводява фактурата и после отговаря, рискува излишни повторения.

Подпис: как да проверите произхода

Вашият адрес е публично достъпен. Всеки би могъл да му изпраща измислени съобщения. Затова сериозните изпращачи подписват всяко съобщение със споделена тайна. Обичаен е HMAC със SHA-256 върху съдържанието, често заедно с времеви печат. GitHub описва метода така: HMAC-SHA256 върху съдържанието, представен шестнадесетично, със заглавката X-Hub-Signature-256. Сравнението трябва да се извършва с функция с постоянно време на изпълнение, за да не могат нападателите да изведат нищо от времето за отговор.

Важни точки за Вашия приемник:

  • Използвайте суровото съдържание. Изчислявайте подписа върху получените байтове, а не върху наново сериализирания JSON. Дори друг нов ред променя подписа.
  • Проверявайте времевия печат. Stripe използва времеви печат в подписа и стандартен толеранс от пет минути, за да предотврати атаки с повторение. Толеранс 0 изключва проверката.
  • Пазете тайната в тайна. Не в кода, не в хранилището, а в променлива на средата или в трезор.

Насоки с отворен код за изпращачи и приемници обединява инициативата Standard Webhooks. Как точно всеки доставчик образува своя подпис, е записано в неговата документация.

Повторения и двойна доставка

Ако Вашият приемник не отговори или отговори с код за грешка, изпращачът опитва отново. Stripe например повтаря според собствената си документация с нарастващи интервали до три дни. Други доставчици имат други правила, някои изключват Webhook след твърде много неуспехи. От това следва:

  • Смятайте с дубликати. Едно и също събитие може да пристигне многократно, дори Вашият приемник да работи правилно. Stripe изрично посочва това.
  • Направете обработването идемпотентно. Това означава: който обработи същото съобщение два пъти, не създава втори резултат. Съхранявайте идентификатора на събитието и прескачайте познатото.
  • Не разчитайте на реда. Събитията могат да пристигнат разменени. При съмнение проверете текущото състояние чрез API.

Сигурност от двете страни

За приемниците: само HTTPS, проверявайте подписа и възрастта, ограничавайте размера на съобщението, не изпълнявайте команди от съдържанието. Третирайте съдържанието като всеки вход отвън.

За изпращачите, които викат адреси на клиенти: Който предлага Webhook, вика адреси, вписани от други. Това е класически път за Server-Side Request Forgery. Нападателят вписва вътрешен адрес. Сървърът го вика от защитената мрежа. Описанието на OWASP посочва като цели например вътрешни услуги и метаданни адреси на облачни доставчици. Разумни защитни мерки:

  • допускайте само https://,
  • разрешавайте адреса при вписването и преди всяко извикване и отхвърляйте частни, локални и резервирани диапазони,
  • не следвайте слепешком пренасочванията,
  • задавайте къси времеви ограничения.

Пример: изпращане на тестово съобщение с curl

С curl и openssl можете да тествате Вашия приемник без истинския изпращач. Скриптът изпраща подписано съобщение, каквото би изпратил изпращач с времеви печат:

GEHEIMNIS="test-geheimnis"
ZEIT=$(date +%s)
INHALT='{"id":"evt_1","typ":"besuch.begonnen","firma":"beispiel-firma.example"}'
SIGNATUR="sha256=$(printf '%s.%s' "$ZEIT" "$INHALT" | openssl dgst -sha256 -hmac "$GEHEIMNIS" | sed 's/^.* //')"

curl -X POST http://localhost:3000/webhook \
  -H "Content-Type: application/json" \
  -H "X-Zeit: $ZEIT" \
  -H "X-Signatur: $SIGNATUR" \
  -d "$INHALT"

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

const http = require('http')
const crypto = require('crypto')
const GEHEIMNIS = process.env.WEBHOOK_GEHEIMNIS || 'test-geheimnis'
const gesehen = new Set() // в реална среда: база данни

http.createServer((req, res) => {
  if (req.method !== 'POST' || req.url !== '/webhook') { res.writeHead(404); return res.end() }
  const teile = []
  req.on('data', t => teile.push(t))
  req.on('end', () => {
    const roh = Buffer.concat(teile).toString('utf8')
    const zeit = req.headers['x-zeit'] || ''
    const erwartet = 'sha256=' + crypto.createHmac('sha256', GEHEIMNIS).update(zeit + '.' + roh).digest('hex')
    const erhalten = String(req.headers['x-signatur'] || '')
    const a = Buffer.from(erwartet), b = Buffer.from(erhalten)
    const echt = a.length === b.length && crypto.timingSafeEqual(a, b)
    const frisch = Math.abs(Date.now() / 1000 - Number(zeit)) < 300
    if (!echt || !frisch) { res.writeHead(401); return res.end() }
    const ereignis = JSON.parse(roh)
    if (!gesehen.has(ereignis.id)) { gesehen.add(ereignis.id); console.log('neu:', ereignis.typ) }
    res.writeHead(200); res.end('ok')
  })
}).listen(3000)

Приемникът проверява подписа и възрастта, прескача познатите идентификатори и отговаря веднага. За производствена работа Ви трябват допълнително HTTPS, ограничение на размера и опашка за по-нататъшната обработка.

Къде Webhook са разпространени

Платежните услуги, платформите за код и инструментите за формуляри съобщават събития чрез Webhook. Може и разпознаването на посетители: ако системата съобщи за фирма, която посещава Вашата страница, тя попада директно в инструмент по Ваш избор. Как това води до система за продажби, показва Как да пренесете посещенията на уебсайта в CRM: 4 пътя в сравнение. Алтернативата чрез заявка описва Кои фирми посещават моя уебсайт? 3 пътя накратко. Какви данни текат при това, обяснява Как работи разпознаването на фирми? Технологията в 6 стъпки.

Често задавани въпроси

Каква е разликата между Webhook и API? При API Вашата система пита, при Webhook изпращачът се обажда сам. И двете могат да се комбинират.

Какво се случва, ако моят приемник се срине? Повечето изпращачи повтарят доставката в продължение на известен период. Колко дълго и колко често, е записано в документацията на доставчика. За пропуските трябва да планирате съпоставяне чрез API.

Достатъчно ли е да проверя адреса на изпращача? Не. Адресите на изпращачите могат да се подправят и се променят. Надежден е само подписът със тайна, която знаете само Вие и изпращачът.

Прочетете още