شرح Webhooks: الحمولات الموقعة ومنطق إعادة المحاولة

Backend2026-10-28TryQuickToolBox

لقد قمت ببناء API وتحتاج الآن إلى إخطار الخدمات الأخرى عند حدوث الأحداث. الاستقصاء (Polling) غير فعال، لذا تلجأ إلى webhooks. ولكن سرعان ما تكتشف أن webhooks يمكن أن تفشل، أو يتم انتحالها، أو تسبب معالجة مكررة. تشرح هذه المقالة كيفية تأمين webhooks باستخدام الحمولات الموقعة وتنفيذ منطق إعادة محاولة قوي.

ما هي Webhooks؟

Webhooks هي عمليات استدعاء HTTP محددة من قبل المستخدم. عندما يحدث حدث في نظامك (مثل نجاح عملية دفع)، ترسل طلب HTTP POST إلى عنوان URL يقدمه المشترك. تحتوي الحمولة عادةً على بيانات الحدث بتنسيق JSON أو نموذج.

تمكّن webhooks التواصل في الوقت الفعلي بين الخدمات دون استقصاء مستمر. وهي مستخدمة على نطاق واسع من قبل بوابات الدفع وأدوات CI/CD ومنصات SaaS.

لماذا تأمين Webhooks؟

بدون أمان، يمكن لأي شخص يعرف عنوان URL لـ webhook إرسال طلبات مزيفة، مما يؤدي إلى تلف البيانات أو الاحتيال. أيضًا، قد يعيد المهاجمون إرسال طلبات قديمة. توقيع الحمولات باستخدام سر مشترك يضمن الأصالة والسلامة.

توقيع الحمولات باستخدام HMAC

HMAC (رمز مصادقة الرسائل القائم على التجزئة) هو طريقة شائعة لتوقيع webhooks. يتشارك المرسل والمستقبل مفتاحًا سريًا. يحسب المرسل HMAC للحمولة باستخدام السر ويضمّنه في رأس (مثل X-Signature). يعيد المستقبل حساب HMAC ويقارنه.

خطوة بخطوة: إرسال webhook موقّع

  1. إنشاء الحمولة (JSON).
  2. حساب HMAC-SHA256 للحمولة باستخدام السر.
  3. تضمين الملخص السداسي عشري في رأس، مثل X-Signature: sha256=....
  4. إرسال طلب POST.
// Node.js example using crypto
const crypto = require('crypto');
const secret = 'your_shared_secret';
const payload = JSON.stringify({ event: 'payment.success', amount: 100 });
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
// Send POST with header X-Signature: sha256=signature

التحقق من التوقيع

على جانب المستقبل، استخرج رأس التوقيع، واحسب HMAC لنص الطلب الخام، وقارن باستخدام مقارنة ثابتة الزمن لمنع هجمات التوقيت.

// Express.js example
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const computed = crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(computed))) {
    return res.status(401).send('Invalid signature');
  }
  // Process payload
  res.status(200).send('OK');
});

ملاحظة: تأكد من استخدام النص الخام، وليس JSON المحلل، لأن التحليل يمكن أن يغير الحمولة.

منع هجمات إعادة الإرسال

ضمّن طابعًا زمنيًا في الحمولة الموقعة وارفض الطلبات الأقدم من بضع دقائق. أيضًا، ضمّن معرف حدث فريدًا واحفظ المعرفات المعالجة لتجنب التكرار.

منطق إعادة المحاولة للتسليم الموثوق

يمكن أن تكون نقاط نهاية webhook معطلة أو بطيئة. نفّذ إعادة المحاولة مع التراجع الأسي والتشتيت (jitter). حدد الحد الأقصى لعدد المحاولات (مثل 5) ومهلة لكل طلب.

استراتيجية إعادة المحاولة

مثال على جدول إعادة المحاولة: إعادة المحاولة الأولى بعد 5 ثوانٍ، الثانية بعد 30 ثانية، الثالثة بعد دقيقتين، الرابعة بعد 10 دقائق، الخامسة بعد ساعة.

التعامل مع حالات الفشل

إذا فشلت جميع المحاولات، سجّل الفشل وأخطر المشترك (مثل عبر البريد الإلكتروني أو لوحة التحكم). وفر طريقة لإعادة إرسال webhooks يدويًا.

مقارنة: الحمولات الموقعة مقابل المصادقة الأساسية

الطريقة الأمان التعقيد حماية إعادة الإرسال
HMAC Signed Payload عالي متوسط نعم (مع طابع زمني)
Basic Auth منخفض منخفض لا
API Key في الرأس متوسط منخفض لا

أفضل الممارسات

الأسئلة الشائعة

كيف أتحقق من توقيع webhook؟

احسب HMAC لنص الطلب الخام باستخدام السر الخاص بك وقارنه برأس التوقيع باستخدام مقارنة ثابتة الزمن.

ماذا أفعل إذا فشل webhook؟

نفّذ إعادة المحاولة مع التراجع الأسي والتشتيت. إذا فشلت جميع المحاولات، سجّل الفشل ووفر خيار إعادة الإرسال اليدوي.

هل يمكنني استخدام webhooks بدون توقيع؟

لا يُنصح بذلك. بدون توقيع، لا يمكنك التحقق من المرسل، مما يجعل نظامك عرضة للانتحال وهجمات إعادة الإرسال.

عند اختبار حمولات webhook، قد تحتاج إلى فحص استجابات JSON. استخدم JSON Formatter الخاص بنا لتنسيق والتحقق من بيانات JSON بسرعة.