Техника · 7 ноември 2026 г. · 6 мин четене
Webhook, обяснен просто: подпис, повторение, сигурност
Какво е Webhook, с какво се различава от API заявката и как да обработвате подпис, повторение и дубликати. С curl и Node.
Webhook е обаждане в обратната посока. Вместо Вашата система да пита една услуга на всеки няколко минути дали нещо се е случило, услугата вика един адрес при Вас, щом се случи. Това спестява заявки и доставя новините по-бързо. За това трябва да осигурите и защитите приемник. Тази статия обяснява и двете.
Webhook или API заявка
| API заявка (Polling) | Webhook | |
|---|---|---|
| Кой започва? | Вашата система | Изпращачът |
| Кога? | По график, например всеки час | Щом настъпи събитие |
| Усилия | Заявки и без новини | Нужен е достъпен приемник |
| Подходящ за | Отчети, съпоставяне, дозареждане | Известяване, препращане |
| Риск | Забавяне до следващата заявка | Съобщението се губи, ако приемникът не отговори |
На практика мнозина комбинират двете: Webhook съобщава за събитието, API извлича при нужда подробностите или запълва пропуските след срив.
Как протича една доставка
- Настъпва събитие, например „постъпило плащане“.
- Изпращачът изпраща POST с JSON към вписания Ваш адрес (HTTPS).
- Вашият приемник проверява подписа, запомня съобщението и отговаря бързо с код от диапазона 2xx.
- Същинската работа Вашата система върши след това.
Стъпка 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.
Достатъчно ли е да проверя адреса на изпращача? Не. Адресите на изпращачите могат да се подправят и се променят. Надежден е само подписът със тайна, която знаете само Вие и изпращачът.