حول المحتوى:
شرح تقنيات التحكم في معدل الطلبات، سياسة الحظر الذكي، التحقق من المستخدمين، واستخدام أدوات جاهزة مع أمثلة لتطبيقات Flask وFastAPI وDjango.
تطبيقات الويب الحديثة تعتمد بشكل أساسي على واجهات API للتواصل بين الواجهة الأمامية، والخدمات الخلفية، والتطبيقات الخارجية. ومع ازدياد عدد المستخدمين والخدمات المتصلة، يصبح من الضروري جدًا تطبيق حماية API rate limiting واستراتيجيات أخرى لمنع إساءة الاستخدام، الهجمات، أو الاستهلاك غير المنضبط للموارد.
في هذا المقال من افهم صح سنشرح مفهوم التحكم في معدل الطلبات (Rate Limiting)، وسياسات الحظر الذكي، والتحقق من المستخدمين، بالإضافة إلى أدوات جاهزة، مع أمثلة عملية في Flask وFastAPI وDjango.
الـ Rate Limiting هي آلية لتحديد عدد الطلبات المسموح بها من مستخدم (أو IP أو Token) خلال إطار زمني معين. الهدف منها:
في مقال آخر تحدثنا عن أفضل ممارسات تصميم RESTful APIs آمن، وذكرنا أن التحكم في معدل الطلبات جزء أساسي من الأمان على مستوى التطبيق.
حصة الاستخدام هي الحد الأقصى للطلبات المسموحة في فترة زمنية معينة، مثل:
النافذة الزمنية يمكن أن تكون ثابتة (Fixed Window) أو متحركة (Sliding Window)، وسنشرح الفرق لاحقًا.
تقسم الزمن إلى نوافذ ثابتة (مثلاً كل دقيقة) وتحسب عدد الطلبات في كل نافذة. إذا تجاوز العميل الحد في النافذة الحالية يتم حظره حتى بداية النافذة التالية.
بدلاً من نافذة ثابتة، يتم حساب الطلبات خلال آخر X ثانية/دقائق بشكل متحرك. يعطي عدالة أكبر ويقلل مشكلة الانفجارات.
هذه الخوارزميات أكثر استخداماً في الأنظمة كبيرة الحجم لأنها مرنة ويمكن ضبطها بدقة.
بدلاً من حظر فوري عند تجاوز الحد، يمكن اتباع سياسة تدريجية:
هذه السياسة تمنع إساءة الاستخدام من سكربتات آلية، مع مراعاة المستخدمين الشرعيين.
في Endpoints حساسة مثل /login أو /reset-password، يمكن إضافة:
بدلاً من كتابة كل شيء داخل الكود الأساسي، يمكن استخدام:
في Flask يمكن استخدام مكتبة جاهزة مثل Flask-Limiter لتطبيق حماية API rate limiting بسهولة.
pip install flask-limiter
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
get_remote_address,
app=app,
default_limits=["100 per minute"] # حد عام لكل الواجهات
)
@app.route("/api/data")
@limiter.limit("10 per second") # حد خاص بهذه الواجهة
def get_data():
return {"message": "OK"}
if __name__ == "__main__":
app.run()
في المثال السابق:
يمكنك أيضًا تخصيص المفتاح المستخدم للـ Rate Limiting ليعتمد على Token بدلاً من IP:
from flask import request
def get_api_key():
return request.headers.get("X-API-Key") or get_remote_address()
إطار FastAPI يدعم التكامل بسهولة مع مكتبات خارجية مثل SlowAPI أو fastapi-limiter، وغالبًا تستخدم Redis كـ Storage.
pip install fastapi-limiter redis
from fastapi import FastAPI, Depends
from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter
import aioredis
app = FastAPI()
@app.on_event("startup")
async def startup():
redis = await aioredis.from_url("redis://localhost", encoding="utf-8", decode_responses=True)
await FastAPILimiter.init(redis)
@app.get("/api/items", dependencies=[Depends(RateLimiter(times=100, seconds=60))])
async def get_items():
return {"items": []}
في هذا المثال:
في Django يمكن استخدام مكتبات جاهزة مثل django-ratelimit، أو بناء Middleware خاص بك. الاستفادة من Middleware في هذه الحالة قوية؛ لأنه يستطيع اعتراض الطلبات قبل وصولها إلى الـ View. لمزيد من التفاصيل حول Middleware راجع: شرح طريقة استخدام Middleware في Django.
pip install django-ratelimit
INSTALLED_APPS = [
# ...
'ratelimit',
]
from django.http import HttpResponse
from ratelimit.decorators import ratelimit
@ratelimit(key='ip', rate='5/m', block=True)
def my_view(request):
return HttpResponse("OK")
في هذا المثال:
يمكنك أيضًا تحديد مفتاح مختلف مثل:
الهدف من الكود التالي تعليمي (ليس للإنتاج)، يوضح فكرة العد على مستوى الـ IP باستخدام Cache:
# middleware.py
import time
from django.core.cache import cache
from django.http import JsonResponse
class SimpleRateLimitMiddleware:
RATE = 100 # 100 طلب
WINDOW = 60 # في 60 ثانية
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
ip = request.META.get('REMOTE_ADDR', 'unknown')
key = f"rl:{ip}"
data = cache.get(key, {'count': 0, 'start': time.time()})
now = time.time()
if now - data['start'] > self.WINDOW:
data = {'count': 0, 'start': now}
data['count'] += 1
cache.set(key, data, timeout=self.WINDOW)
if data['count'] > self.RATE:
return JsonResponse(
{"detail": "Too many requests"},
status=429
)
response = self.get_response(request)
return response
ثم تضيف الـ Middleware في MIDDLEWARE داخل settings.py.
اختيار مكان تخزين العدادات يؤثر على الأداء والدقة:
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.الـ Rate Limiting وحده لا يكفي؛ يجب دمجه مع:
حماية واجهات API من إساءة الاستخدام ليست خيارًا إضافيًا؛ بل ضرورة لأي نظام يعتمد على الإنترنت. استخدام حماية API rate limiting مع:
سيساعدك على بناء واجهات مستقرة، آمنة، وتتحمل عددًا كبيرًا من المستخدمين دون سقوط أو استهلاك مفرط للموارد. ابدأ بتحديد حدود معقولة، راقب السلوك، وعدّل القيم والخوارزميات حتى تصل إلى التوازن بين الأمان وتجربة الاستخدام الجيدة.
شرح تقنيات التحكم في معدل الطلبات، سياسة الحظر الذكي، التحقق من المستخدمين، واستخدام أدوات جاهزة مع أمثلة لتطبيقات Flask وFastAPI وDjango.
مساحة اعلانية