تحديد معدل الطلبات في JavaScript (Node.js): حماية API باستخدام express-rate-limit
في تطوير الويب الحديث، تعد حماية تطبيقات الخادم من الأحمال الزائدة والهجمات الضارة مهمة بالغة الأهمية. من أكثر آليات الحماية فعالية هو تحديد معدل الطلبات. يسمح هذا الأسلوب بالتحكم في عدد الطلبات التي يمكن للعميل (عنوان IP، مستخدم أو جلسة) إرسالها إلى الخادم خلال فترة زمنية محددة. في نظام Node.js و Express، المكتبة الأكثر شيوعًا وموثوقية لتطبيق تحديد معدل الطلبات هي express-rate-limit.
ما هو تحديد معدل الطلبات ولماذا هو مطلوب؟
تحديد معدل الطلبات هو تقنية تُستخدم لإدارة حركة المرور على الشبكة. تمنع إساءة استخدام موارد الخادم، وتحمي من:
- هجمات DoS/DDoS — الطلبات الجماعية بهدف تعطيل الخادم.
- هجمات القوة العمياء — تخمين كلمات المرور أو رموز الوصول.
- Web scraping — جمع البيانات تلقائيًا من الموقع.
- الاستخدام المفرط لـ API — عندما يستهلك عميل واحد موارد أكثر من المسموح.
بدون تحديد معدل الطلبات، قد يصبح تطبيقك عرضة للخطر وغير مستقر، خاصة مع نمو قاعدة المستخدمين.
مكتبة express-rate-limit
express-rate-limit هي middleware لـ Express.js توفر طريقة بسيطة ومرنة لتقييد الطلبات. يتم تضمينها في سلسلة معالجة الطلبات وتتتبع تلقائيًا عدد الزيارات من كل عميل. تدعم المكتبة مخازن مختلفة (في الذاكرة، Redis، MongoDB وغيرها)، مما يجعلها قابلة للتوسع للأنظمة الموزعة.
التثبيت
للبدء، قم بتثبيت المكتبة عبر npm:
npm install express-rate-limitالاستخدام الأساسي
أبسط مثال هو تقييد جميع مسارات التطبيق إلى 100 طلب في الساعة من عنوان IP واحد:
const rateLimit = require('express-rate-limit');const express = require('express');const app = express();
// إنشاء المحددconst limiter = rateLimit({ windowMs: 60 * 60 * 1000, // ساعة واحدة max: 100, // الحد الأقصى 100 طلب message: 'عدد كبير جدًا من الطلبات من عنوان IP الخاص بك. يرجى المحاولة لاحقًا.', standardHeaders: true, // إرجاع رؤوس RateLimit-* القياسية legacyHeaders: false, // تعطيل رؤوس X-RateLimit-*});
// تطبيق على جميع المساراتapp.use(limiter);
app.get('/', (req, res) => { res.send('الصفحة الرئيسية');});
app.listen(3000, () => { console.log('الخادم يعمل على المنفذ 3000');});الإعداد لمسارات مختلفة
غالبًا ما تكون هناك حاجة إلى تحديد مختلف لنقاط النهاية المختلفة. على سبيل المثال، يمكن تعيين حد أكثر صرامة لمسار تسجيل الدخول:
const rateLimit = require('express-rate-limit');
// حد صارم لـ /api/loginconst loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 دقيقة max: 5, // 5 محاولات تسجيل دخول message: { error: 'عدد كبير جدًا من محاولات تسجيل الدخول. حاول بعد 15 دقيقة.', retryAfter: 15 }, keyGenerator: (req) => { // استخدام IP + اسم المستخدم لمنع أكثر دقة return req.ip + req.body.username; }});
app.post('/api/login', loginLimiter, (req, res) => { // منطق المصادقة res.send('تم تسجيل الدخول');});
// حد مرن لـ API العامconst apiLimiter = rateLimit({ windowMs: 60 * 1000, // دقيقة واحدة max: 30, // 30 طلبًا في الدقيقة message: 'تم تجاوز حد طلبات API.'});
app.use('/api/', apiLimiter);إمكانيات متقدمة
مخازن مخصصة
افتراضيًا، يتم تخزين البيانات في ذاكرة العملية. للإنتاج، نوصي