Tehnika · 7. studenoga 2026. · 5 min čitanja
Webhookovi jednostavno objašnjeni: potpis, ponavljanje, sigurnost
Što je webhook, po čemu se razlikuje od API upita i kako postupati s potpisom, ponavljanjem i duplikatima. S curlom i Nodeom.
Webhook je poziv u suprotnom smjeru. Umjesto da Vaš sustav svakih nekoliko minuta pita neku uslugu je li se nešto dogodilo, usluga poziva adresu kod Vas čim se to dogodi. To štedi upite i brže donosi novosti. Zauzvrat morate osigurati primatelja i zaštititi ga. Ovaj članak objašnjava oboje.
Webhook ili API upit
| API upit (polling) | Webhook | |
|---|---|---|
| Tko započinje? | Vaš sustav | Pošiljatelj |
| Kada? | Prema rasporedu, primjerice svaki sat | Čim nastupi događaj |
| Trud | Upiti i bez novosti | Potreban dostupan primatelj |
| Dobro za | Izvješća, usklađivanje, naknadno učitavanje | Obavijesti, prosljeđivanje |
| Rizik | Kašnjenje do sljedećeg upita | Poruka se gubi ako primatelj ne odgovori |
U praksi mnogi kombiniraju oboje: webhook prijavljuje događaj, a API po potrebi dohvaća pojedinosti ili zatvara rupe nakon ispada.
Kako teče isporuka
- Nastupi događaj, primjerice „uplata je stigla“.
- Pošiljatelj šalje POST s JSON-om na Vašu pohranjenu adresu (HTTPS).
- Vaš primatelj provjerava potpis, pamti poruku i brzo odgovara kodom iz raspona 2xx.
- Pravi posao Vaš sustav obavlja nakon toga.
Korak 3 je važan. Stripe u dokumentaciji o webhookovima preporučuje da se odmah vrati kod 2xx prije nego što se pokrene složena logika koja bi mogla izazvati istek vremena. Tko prvo knjiži račun, a tek onda odgovara, riskira nepotrebna ponavljanja.
Potpis: kako provjeriti podrijetlo
Vaša je adresa javno dostupna. Svatko bi joj dakle mogao slati izmišljene poruke. Zato ozbiljni pošiljatelji svaku poruku potpisuju zajedničkom tajnom. Uobičajen je HMAC sa SHA-256 preko sadržaja, često zajedno s vremenskom oznakom. GitHub opisuje postupak ovako: HMAC-SHA256 preko sadržaja, prikazan heksadecimalno, sa zaglavljem X-Hub-Signature-256. Usporedba se treba obaviti funkcijom s konstantnim trajanjem kako napadači iz vremena odgovora ne bi mogli ništa zaključiti.
Važne točke za Vašeg primatelja:
- Koristiti sirovi sadržaj. Potpis izračunajte preko primljenih bajtova, a ne preko ponovno serijaliziranog JSON-a. Već i drugačiji prijelom retka mijenja potpis.
- Provjeriti vremensku oznaku. Stripe koristi vremensku oznaku u potpisu i zadanu toleranciju od pet minuta kako bi spriječio napade ponavljanjem. Tolerancija 0 isključuje provjeru.
- Tajnu držati tajnom. Ne u kodu, ne u repozitoriju, nego u varijabli okruženja ili trezoru.
Smjernice otvorenog koda za pošiljatelje i primatelje okuplja inicijativa Standard Webhooks. Kako svaki pružatelj konkretno gradi svoj potpis, stoji u njegovoj dokumentaciji.
Ponavljanja i dvostruka isporuka
Ako Vaš primatelj ne odgovori ili odgovori kodom pogreške, pošiljatelj pokušava ponovno. Stripe, primjerice, prema vlastitoj dokumentaciji ponavlja s rastućim razmacima do tri dana. Drugi pružatelji imaju druga pravila, neki isključuju webhook nakon previše neuspjeha. Iz toga slijedi:
- Računajte s duplikatima. Isti događaj može stići više puta, čak i kad Vaš primatelj radi ispravno. Stripe na to izričito upozorava.
- Obradu učinite idempotentnom. To znači: tko istu poruku obradi dvaput, ne stvara drugi rezultat. Pohranite oznaku događaja i preskočite poznato.
- Ne oslanjajte se na redoslijed. Događaji mogu stići zamijenjenim redoslijedom. U slučaju sumnje provjerite aktualno stanje putem API-ja.
Sigurnost na obje strane
Za primatelje: samo HTTPS, provjeriti potpis i starost, ograničiti veličinu poruke, ne izvršavati naredbe iz sadržaja. Sadržaj tretirajte kao svaki ulaz izvana.
Za pošiljatelje koji pozivaju adrese klijenata: tko nudi webhookove, poziva adrese koje su unijeli drugi. To je klasičan put za Server-Side Request Forgery. Napadač unese internu adresu. Poslužitelj je poziva iz zaštićene mreže. OWASP-ov opis kao ciljeve navodi primjerice interne usluge i adrese metapodataka pružatelja oblaka. Smislene zaštitne mjere:
- dopustiti samo
https://, - adresu razriješiti pri unosu i prije svakog poziva te odbiti privatne, lokalne i rezervirane raspone,
- ne slijediti preusmjeravanja naslijepo,
- postaviti kratka vremenska ograničenja.
Primjer: slanje probne poruke curlom
Pomoću curla i openssla možete testirati svog primatelja bez pravog pošiljatelja. Skripta šalje potpisanu poruku kakvu bi poslao pošiljatelj s vremenskom oznakom:
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"
Primjer: mali primatelj u Node.js-u
const http = require('http')
const crypto = require('crypto')
const GEHEIMNIS = process.env.WEBHOOK_GEHEIMNIS || 'test-geheimnis'
const gesehen = new Set() // u stvarnosti: baza podataka
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)
Primatelj provjerava potpis i starost, preskače poznate oznake i odmah odgovara. Za pogon dodatno trebate HTTPS, ograničenje veličine i red čekanja za daljnju obradu.
Gdje su webhookovi rašireni
Platne usluge, platforme za kod i alati za obrasce javljaju događaje webhookom. To može i prepoznavanje posjetitelja: ako sustav prijavi tvrtku koja posjećuje Vašu stranicu, ona odmah završava u alatu po Vašem izboru. Kako to vodi u prodajni sustav, pokazuje Kako posjete web stranici dovesti u CRM. Alternativu putem upita opisuje Koje tvrtke posjećuju moju web stranicu?. Koji podaci pritom teku, objašnjava Kako funkcionira prepoznavanje tvrtki?.
Često postavljana pitanja
Koja je razlika između webhooka i API-ja? Kod API-ja Vaš sustav pita, kod webhooka se pošiljatelj sam javlja. Oboje se može kombinirati.
Što se događa ako moj primatelj ispadne? Većina pošiljatelja ponavlja isporuku tijekom određenog razdoblja. Koliko dugo i koliko često, stoji u dokumentaciji pružatelja. Za rupe biste trebali planirati usklađivanje putem API-ja.
Je li dovoljno provjeriti adresu pošiljatelja? Ne. Adrese pošiljatelja mogu se lažirati i mijenjaju se. Pouzdan je samo potpis s tajnom koju znate samo Vi i pošiljatelj.