Güvenlik ve HMAC imzalama
Savebase’in gönderdiği her webhook isteği HMAC-SHA256 ile imzalanır; böylece gerçekten Savebase’ten geldiğini ve aktarım sırasında değiştirilmediğini doğrulayabilirsiniz. Bir webhook olayını işlemeden önce bu imzayı her zaman doğrulamalısınız.
İmzalama Nasıl Çalışır
Savebase imzayı, webhook’unuzun şu değerini kullanarak ham istek gövdesine HMAC-SHA256 uygulayarak hesaplar: İmzalama sırrı anahtarıyla. Sonuç şu alanda gönderilir: X-Savebase-Signature başlığı şu şekilde: sha256=<hex-digest>.
Ham gövdeyi kullan
HMAC’yi her zaman şunun üzerinden hesaplayın: ham, değiştirilmemiş istek gövdesi baytları — yeniden serileştirilmiş JSON nesnesi değil. JSON’u ayrıştırıp yeniden metne dönüştürmek boşlukları ve anahtar sırasını değiştirerek imza doğrulamasını bozabilir.
| Başlık | Değer biçimi |
|---|---|
X-Savebase-Signature | sha256=abcdef0123... |
X-Savebase-Event | post.saved |
User-Agent | Savebase-Webhook/1.0 |
Node.js / Express
bash
const crypto = require('crypto');
function verifySignature(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signatureHeader, 'utf8')
);
}
app.post(
'/savebase-webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const sig = req.headers['x-savebase-signature'];
if (!sig || !verifySignature(req.body, sig, process.env.SAVEBASE_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
console.log('Event:', event.event, event.data.id);
res.sendStatus(200);
}
);Python / Flask
bash
import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = os.environ['SAVEBASE_WEBHOOK_SECRET']
@app.route('/savebase-webhook', methods=['POST'])
def handle_webhook():
sig_header = request.headers.get('X-Savebase-Signature', '')
raw_body = request.get_data()
expected = 'sha256=' + hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, sig_header):
abort(401)
payload = request.get_json()
print('Received event:', payload['event'])
return '', 200PHP
bash
<?php
$secret = getenv('SAVEBASE_WEBHOOK_SECRET');
$rawBody = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_X_SAVEBASE_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $sigHeader)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($rawBody, true);
error_log('Received: ' . $event['event']);
http_response_code(200);Güvenlik için iyi uygulamalar
- Hızlı yanıt verin. Bir değer döndürün:
200 OK10 saniye içinde. Savebase 10 saniyede zaman aşımına uğrar ve teslimi başarısız işaretler. Ağır işleri arka plan görevine aktar. - İmzalama sırrınızı asla günlüğe kaydetmeyin. Bir parola gibi koru. Şuradan yenile:
Settings → Webhooksele geçirildiğini düşünüyorsan. - Yalnızca HTTPS kullan. Savebase şifrelenmemiş HTTP uç noktalarını reddeder.
- Zamanlama güvenli karşılaştırma kullan. Her zaman kullanın:
crypto.timingSafeEqual(Node),hmac.compare_digest(Python) veyahash_equals(PHP) — asla düz bir===. - Hataları kendiniz yönetin. Savebase teslim sonucunu kaydeder, ancak mevcut uygulama başarısız istekleri otomatik yeniden denemez veya tekrar oynatmaz.