# Webhookid lihtsalt selgitatuna: allkiri, kordus, turvalisus

> Mis on webhook, kuidas see erineb API-päringust ja kuidas käsitleda allkirja, kordust ja duplikaate. Näidetega curl'i ja Node'iga.

Quelle: https://whovisit.app/et/blog/webhookid-lihtsalt-selgitatud-allkiri-kordus
Veröffentlicht: 2026-11-07
Herausgeber: Whovisit (ARAVILO, Innsbruck)

Webhook on kõne vastupidises suunas. Selle asemel et teie süsteem küsiks teenuselt iga mõne minuti järel, kas midagi on juhtunud, kutsub teenus teie aadressi, niipea kui see juhtub. See säästab päringuid ja toob uudised kiiremini. Selle eest peate vastuvõtja ette valmistama ja kaitsma. See artikkel selgitab mõlemat.

## Webhook või API-päring

| | API-päring (Polling) | Webhook |
|---|---|---|
| Kes alustab? | Teie süsteem | Saatja |
| Millal? | Ajakava järgi, näiteks tunnis | Niipea kui sündmus toimub |
| Töömaht | Päringud ka ilma uudisteta | Vajalik kättesaadav vastuvõtja |
| Hea mille jaoks | Aruanded, võrdlus, järellaadimine | Teavitus, edastamine |
| Risk | Viivitus järgmise päringuni | Sõnum läheb kaduma, kui vastuvõtja ei vasta |

Praktikas kombineerivad paljud mõlemat: webhook teatab sündmusest, API toob vajaduse korral üksikasjad või täidab lüngad pärast katkestust.

## Kuidas saatmine käib

1. Toimub sündmus, näiteks „makse saabunud“.
2. Saatja saadab POST-päringu JSON-iga teie määratud aadressile (HTTPS).
3. Teie vastuvõtja kontrollib allkirja, jätab sõnumi meelde ja vastab kiiresti 2xx-vahemiku koodiga.
4. Tegeliku töö teeb teie süsteem seejärel.

Samm 3 on oluline. Stripe soovitab [webhooki dokumentatsioonis](https://docs.stripe.com/webhooks) anda kohe tagasi 2xx-kood enne, kui käivitub keeruline loogika, mis võib vallandada ajalõpu. Kes kõigepealt arve raamatupidamisse kannab ja siis vastab, riskib tarbetute kordustega.

## Allkiri: kuidas päritolu kontrollida

Teie aadress on avalikult kättesaadav. Igaüks võiks sellele seega välja mõeldud sõnumeid saata. Seetõttu allkirjastavad usaldusväärsed saatjad iga sõnumi ühise saladusega. Tavaline on HMAC koos SHA-256-ga üle sisu, sageli koos ajatempliga. [GitHub kirjeldab menetlust](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries) nii: HMAC-SHA256 üle sisu, esitatud kuueteistkümnendsüsteemis, päisega `X-Hub-Signature-256`. Võrdlus peaks toimuma konstantse tööajaga funktsiooniga, et ründajad ei saaks vastuseaegadest midagi tuletada.

Olulised punktid teie vastuvõtja jaoks:

- **Kasutada toorsisu.** Arvutage allkiri üle vastuvõetud baitide, mitte uuesti serialiseeritud JSON-i. Juba teistsugune reavahetus muudab allkirja.
- **Kontrollida ajatemplit.** Stripe kasutab allkirjas ajatemplit ja vaiketaluvust viis minutit, et vältida kordusrünnakuid. Taluvus 0 lülitab kontrolli välja.
- **Saladust salajas hoida.** Mitte koodis, mitte hoidlas, vaid keskkonnamuutujas või varamus.

Avatud lähtekoodiga juhised saatjatele ja vastuvõtjatele koondab algatus [Standard Webhooks](https://www.standardwebhooks.com/). Kuidas iga pakkuja oma allkirja täpselt moodustab, seisab tema dokumentatsioonis.

## Kordused ja topeltsaatmine

Kui teie vastuvõtja ei vasta või vastab veakoodiga, proovib saatja uuesti. Stripe näiteks kordab oma dokumentatsiooni järgi kasvavate vahedega kuni kolm päeva. Teistel pakkujatel on teised reeglid, mõned lülitavad webhooki liiga paljude ebaõnnestumiste järel välja. Sellest järeldub:

- **Arvestage duplikaatidega.** Sama sündmus võib saabuda mitu korda, ka siis, kui teie vastuvõtja töötab õigesti. Stripe juhib sellele sõnaselgelt tähelepanu.
- **Tehke töötlemine idempotentseks.** See tähendab: kes töötleb sama sõnumit kaks korda, ei tekita teist tulemust. Salvestage sündmuse tunnus ja jätke tuttav vahele.
- **Ärge toetuge järjekorrale.** Sündmused võivad saabuda vahetatud järjekorras. Kahtluse korral kontrollige praegust seisu API kaudu.

## Turvalisus mõlemal poolel

**Vastuvõtjatele:** ainult HTTPS, kontrollige allkirja ja vanust, piirake sõnumi suurust, ärge käivitage sisust käske. Käsitlege sisu nagu iga väljastpoolt tulevat sisendit.

**Saatjatele, kes kutsuvad klientide aadresse:** kes pakub webhooke, kutsub aadresse, mille on sisestanud teised. See on klassikaline tee Server-Side Request Forgery jaoks. Ründaja sisestab sisemise aadressi. Server kutsub selle kaitstud võrgust välja. [OWASP kirjeldus](https://community.owasp.org/attacks/Server_Side_Request_Forgery) nimetab sihtmärkidena näiteks sisemisi teenuseid ja pilvepakkujate metaandmeaadresse. Mõistlikud kaitsemeetmed:

- lubada ainult `https://`,
- lahendada aadress sisestamisel ja enne igat kutset ning lükata tagasi privaatsed, kohalikud ja reserveeritud vahemikud,
- ümbersuunamisi mitte pimesi järgida,
- seada lühikesed ajalimiidid.

## Näide: testsõnumi saatmine curl'iga

Curl'i ja openssl'iga saate oma vastuvõtjat testida ilma päris saatjata. Skript saadab allkirjastatud sõnumi, nagu saadaks saatja ajatempliga:

```bash
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"
```

## Näide: väike vastuvõtja Node.js-is

```js
const http = require('http')
const crypto = require('crypto')
const GEHEIMNIS = process.env.WEBHOOK_GEHEIMNIS || 'test-geheimnis'
const gesehen = new Set() // päriselus: andmebaas

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)
```

Vastuvõtja kontrollib allkirja ja vanust, jätab tuttavad tunnused vahele ja vastab kohe. Tööks vajate lisaks HTTPS-i, suurusepiirangut ja järjekorda edasitöötluse jaoks.

## Kus webhookid levinud on

Maksete teenused, koodiplatvormid ja vormitööriistad teatavad sündmustest webhooki kaudu. Seda oskab ka külastajate tuvastamine: kui süsteem teatab ettevõttest, kes teie lehte külastab, jõuab see otse teie valitud tööriista. Kuidas see viib müügisüsteemi, näitab artikkel [Veebilehe külastuste toomine CRM-i](https://whovisit.app/blog/website-besuche-ins-crm). Alternatiivi päringu teel kirjeldab [Millised ettevõtted minu veebilehte külastavad?](https://whovisit.app/blog/welche-firmen-besuchen-meine-website). Millised andmed seejuures liiguvad, selgitab [Kuidas ettevõtete tuvastamine toimib?](https://whovisit.app/blog/firmenerkennung-website-technik).

## Korduma kippuvad küsimused

**Mis vahe on webhookil ja API-l?** API puhul küsib teie süsteem, webhooki puhul annab saatja ise märku. Mõlemat saab kombineerida.

**Mis juhtub, kui minu vastuvõtja kukub välja?** Enamik saatjaid kordab saatmist teatud aja jooksul. Kui kaua ja kui sageli, seisab pakkuja dokumentatsioonis. Lünkade jaoks peaksite ette nägema võrdluse API kaudu.

**Kas piisab saatja aadressi kontrollimisest?** Ei. Saatja aadresse saab võltsida ja need muutuvad. Usaldusväärne on ainult allkiri saladusega, mida teavad ainult teie ja saatja.
