خطافات الويب (Webhooks) هي إحدى أقوى الطرق لتلقي تحديثات في الوقت الفعلي من خدمات الطرف الثالث. يمكن لطلب HTTP POST واحد من Stripe أو GitHub أو Shopify أو Twilio أن يؤدي إلى تشغيل منطق عمل حاسم في تطبيقك — كتحصيل رسوم من عميل، أو تحديث مستودع، أو شحن طلب، أو إرسال رسالة تأكيد نصية.
لكن كل طلب خطاف ويب يصل عبر الإنترنت العام. وهذا يعني أن أي شخص يخمن أو يكتشف عنوان URL لخطاف الويب الخاص بك يمكنه إرسال حمولات ضارة تبدو مشروعة تمامًا. بدون المصادقة الصحيحة، لا يملك تطبيقك طريقة للتمييز بين حدث حقيقي وحدث مزور.
هنا يأتي دور التحقق من توقيع خطاف الويب (webhook signature verification). إنها آلية بسيطة وموحدة تضمن أن كل طلب خطاف ويب وارد هو بالفعل من الخدمة التي تتوقعها ولم يتم تعديله أثناء النقل.
في هذا الدليل الشامل، ستتعلم بالضبط كيف يعمل التحقق من توقيع خطاف الويب، وكيفية تنفيذه بشكل صحيح في اللغات الشائعة. سترى أيضًا الأخطاء الشائعة التي يجب تجنبها وكيفية اختبار كل شيء من البداية إلى النهاية — بسرعة وموثوقية.
زر
ما هو التحقق من توقيع خطاف الويب؟
التحقق من توقيع خطاف الويب هو عملية التأكد من أن طلب خطاف الويب الوارد يأتي بالفعل من الخدمة التي تتوقعها ولم يتم التلاعب به.
يستخدم معظم المزودين HMAC (رمز مصادقة الرسائل المستند إلى التجزئة) مع SHA-256 أو SHA-512. تقوم الخدمة بالحساب:
signature = HMAC-SHA256(secret_key, payload)
ثم يرسلون التوقيع في رأس (عادةً X-Signature، Signature، أو X-Hub-Signature-256).
الخادم الخاص بك:
- يتلقى الحمولة كبايتات خام (مهم!)
- يعيد حساب HMAC باستخدام سرك المخزن
- يقارن التوقيع المحسوب مع التوقيع المستلم
إذا تطابقا تمامًا، يمكنك معالجة خطاف الويب. وإلا، فإنك تُرجع HTTP 401 أو 403.
لماذا HMAC-SHA256 هو المعيار الصناعي
يختار المزودون HMAC-SHA256 لأسباب وجيهة:
- سريع: حتى على الأجهزة المتواضعة، فهو سريع للغاية.
- آمن: لا يزال SHA-256 غير مخترق في عام 2025.
- بسيط: مفتاح سري واحد، لا توجد أزواج مفاتيح عامة/خاصة لإدارتها.
- موحد: المكتبات في كل لغة تنفذه بشكل صحيح.
تستخدم GitHub وStripe وShopify وSlack وعشرات الخدمات الأخرى جميعها HMAC-SHA256.
كيفية تنفيذ التحقق من توقيع خطاف الويب في Node.js
لنبدأ بمثال واقعي في Node.js.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const computedSignature = hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(signature)
);
}
نقاط رئيسية يجب ملاحظتها:
- استخدم دائمًا
crypto.timingSafeEqualلمنع هجمات التوقيت. - لا تستخدم أبدًا
===على السلاسل النصية — إنها نقطة ضعف. - استخدم
Buffer.from()لضمان مقارنة بوقت ثابت.
مثال على Express middleware:
app.post('/webhooks/stripe', (req, res, next) => {
const signature = req.headers['stripe-signature'];
const secret = process.env.STRIPE_WEBHOOK_SECRET;
// Get raw body (Express needs middleware to preserve raw body)
const rawBody = req.rawBody || req.body; // use body-parser with verify option
if (!verifyWebhookSignature(rawBody, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Signature is valid → process the event
next();
});
تنفيذ Python (FastAPI + Pydantic)
from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
app = FastAPI()
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed, signature)
@app.post("/webhooks/github")
async def github_webhook(request: Request):
signature = request.headers.get("X-Hub-Signature-256")
if not signature:
raise HTTPException(status_code=401, detail="Missing signature")
payload = await request.body()
if not verify_signature(payload, signature.split('=')[1], SECRET):
raise HTTPException(status_code=401, detail="Invalid signature")
# Process webhook
return {"status": "ok"}
الأخطاء الشائعة التي يرتكبها المطورون (وكيفية تجنبها)
1. استخدام JSON.stringify() أو جسم (Body) محلل
تقوم العديد من الأطر بتحليل JSON تلقائيًا. وهذا يعطل التحقق لأن المسافات البيضاء وترتيب المفاتيح والتنسيق تختلف.
الحل: قم دائمًا بالتقاط الجسم الخام قبل التحليل.
في Express: استخدم body-parser مع { verify: true }
في FastAPI: استخدم await request.body()
2. مقارنة السلاسل النصية باستخدام ===
يمكن لهجمات التوقيت أن تسرب المعلومات. استخدم crypto.timingSafeEqual أو hmac.compare_digest.
3. تخزين الأسرار في الكود
استخدم متغيرات البيئة أو مديري الأسرار (مثل AWS Secrets Manager, HashiCorp Vault، إلخ).
4. نسيان التعامل مع هجمات إعادة التشغيل
يضم معظم المزودين طابعًا زمنيًا. تحقق من أن الحدث حديث (على سبيل المثال، خلال 5 دقائق).
const timestamp = req.headers['X-Signature-Timestamp'];
if (Date.now() - timestamp > 5 * 60 * 1000) {
return res.status(401).send('Timestamp too old');
}
5. استخدام SHA-1 (لا يزال يحدث!)
أوقفت GitHub دعم SHA-1 في عام 2022. استخدم دائمًا SHA-256.
اختبار التحقق من توقيع خطاف الويب باستخدام Apidog
يعد اختبار خطافات الويب يدويًا أمرًا مؤلمًا. ترسل طلبًا، تتحقق من السجلات، تصلح، وتكرر.
Apidog يجعل هذا سهلاً:
في مشروع Apidog الخاص بك، انقر فوق أيقونة + في الشريط الجانبي الأيسر واختر "New Other Protocol APls" > "Webhook".
بعد إنشاء خطاف الويب (Webhook)، املأ الحقول التالية في المحرر:طريقة الطلب (Request Method): عادةً POST.اسم خطاف الويب (Webhook name): سيظهر هذا في وثائق API وتصدير OpenAPI، مثل order.عنوان URL للتصحيح (اختياري) (Debug URL(optional)): هو عنوان URL الفعلي المستخدم لإرسال طلبات الاختبار. ملاحظة: هذا لأغراض الاختبار فقط ولن يتم تضمينه في الوثائق.معلومات أخرى (Other Info): مثل جسم الطلب (request body).
انقر على Save بمجرد إكمال جميع الحقول المطلوبة.
ما عليك سوى إدخال عنوان URL الخاص بخطاف الويب في حقل Debug URL، ثم انقر على Send لمحاكاة استدعاء خطاف ويب.
لقد وفرت ساعات من تصحيح الأخطاء باستخدام محاكي خطافات الويب من Apidog. إنه يدعم حتى تنسيق stripe-signature الدقيق الخاص بـ Stripe وبادئة sha256=... الخاصة بـ GitHub.
مثال واقعي: التحقق من خطافات الويب (Webhooks) من Stripe
يستخدم Stripe تنسيق رأس خاص:
stripe-signature: t=1681234567,v1=abc123...,v0=def456...
يجب عليك:
- استخراج الطابع الزمني
t= - استخراج التوقيع
v1=(المفضل) - إعادة الحساب باستخدام
payload + timestamp - مقارنة الجزء
v1فقط
يوفر Stripe مكتبات رسمية للتعامل مع هذا التعقيد:
const stripe = require('stripe')('sk_...');
stripe.webhooks.constructEvent(payload, sigHeader, endpointSecret);
ولكن فهم HMAC الأساسي أمر بالغ الأهمية عندما تحتاج إلى تنفيذه بنفسك.
مواضيع متقدمة: تحمل التوقيعات المتعددة
يرسل بعض المزودين (مثل Stripe) توقيعات متعددة للتوافق مع الإصدارات السابقة. يجب أن يقوم الكود الخاص بك بـ:
- تقسيم الرأس بواسطة
, - تجربة كل منها
- القبول إذا تطابق أي منها
أفضل ممارسات الأمان في عام 2025
- تدوير أسرار خطاف الويب كل 90 يومًا.
- استخدام الأسرار قصيرة الأمد عندما يكون ذلك ممكنًا.
- تسجيل عمليات التحقق الفاشلة ولكن لا تسجل السر أبدًا.
- تحديد معدل استدعاء نقاط نهاية خطاف الويب لمنع هجمات القوة الغاشمة.
- استخدام HTTPS دائمًا.
الخلاصة: خطوة تحقق صغيرة، مكسب أمني كبير
قد يبدو التحقق من توقيع خطاف الويب تفصيلاً صغيرًا. لكنه الفارق بين تطبيق آمن وتطبيق يمكن للمهاجمين استغلاله بسهولة.
نفذه بشكل صحيح، اختبره بدقة باستخدام أدوات مثل Apidog، ونام قرير العين مع العلم أن عمليات التكامل الخاصة بك محمية.
حمّل Apidog مجانًا اليوم وتحقق من أول خطاف ويب خاص بك في أقل من 5 دقائق. إنها أسرع طريقة لإثبات أن الكود الخاص بك يعمل بالفعل.
زر
