تقنيات وتطبيق
تأمين واجهات البرمجة (APIs): دفاع متعمق وتحديد معدل ذكي
١٥ أكتوبر ٢٠٢٦ · 8 دقائق قراءة
الأمان ليس جدار حماية واحد: مبدأ الدفاع المتعمق
يعتقد العديد من المطورين أن وضع جدار ناري (Firewall) أمام واجهة البرمجة (API) أو استخدام مكتبة JWT كافٍ تماماً لحماية النظام. لكن في الواقع، الهجمات الحديثة على الـ APIs تستهدف ثغرات منطق الأعمال (Business Logic Flaws): مثل استنزاف الموارد، أو التخمين الآلي على المسارات، أو استخراج بيانات سرية بسبب نماذج إرجاع متساهلة.
الحماية الحقيقية تعتمد على الدفاع المتعمق (Defense in Depth): طبقات متعددة من التدابير الأمنية المستقلة، بحيث إذا اخترق المهاجم طبقة واحدة، توقفه الطبقة التالية فوراً.
1. تحديد المعدل متعدد الطبقات (Tiered Rate Limiting)
وضع حد موحد لجميع المسارات (مثلاً: 100 طلب في الدقيقة لكل عنوان IP) هو استراتيجية ساذجة:
- فالمستخدم العادي الذي يتصفح الواجهة سيصل لهذا الحد بسرعة عند تحميل الصفحات.
- بينما المهاجم الذي يخمن كلمات المرور على مسار
/loginسيتمكن من إرسال 100 محاولة في الدقيقة دون عائق!
التصميم السليم: تحديد المعدل حسب حساسية المسار
- المسارات العامة الخفيفة (GET /items): نافذة متساهلة (120 طلب / دقيقة لكل IP).
- المسارات الحساسة للمصادقة (POST /auth/login): نافذة شديدة الصرامة (5 محاولات فاشلة / دقيقة لكل IP + اسم المستخدم).
- المسارات المكلفة حوسبياً (POST /reports/generate): حجز بالحصص (Quota) لكل مستأجر موثوق (مثلاً: 10 تقارير في الساعة).
يتم تطبيق ذلك عبر سكربتات Lua الذرية في Redis لتفادي سباقات التزامن بين العمليات المختلفة.
2. منع تسريب البيانات عبر نماذج Pydantic الصارمة
أحد أخطر التهديدات في قائمة OWASP لأمان الـ APIs هو تسريب الكائنات الزائدة (Excessive Data Exposure): عندما يُرجع المسار كائن قاعدة البيانات كاملاً:
# خطير جداً: يرسل جميع أعمدة جدول المستخدم بما فيها password_hash و internal_role!
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = await repo.get_by_id(user_id)
return user # كارثة أمنية
القاعدة الصارمة: لا تخرج بيانات بدون Response Model صريح
class UserPublicResponse(BaseModel):
id: int
username: str
display_name: str
created_at: datetime
class Config:
from_attributes = True
@app.get("/users/{user_id}", response_model=UserPublicResponse)
async def get_user(user_id: int):
user = await repo.get_by_id(user_id)
return user # Pydantic يضمن تصفية وإسقاط أي حقل غير معلن
بهذا الشكل، حتى لو أضيف عمود جديد يحتوي على بيانات حساسة في قاعدة البيانات، لن يظهر للمستخدم أبداً.
3. تأمين رؤوس الأمان (Security Headers) وسياسة CORS
تجاهل رؤوس HTTP الأمنية يفتح الباب لهجمات Clickjacking و MIME Sniffing:
@app.middleware("http")
async def add_security_headers(request: Request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "SAMEORIGIN"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
response.headers["Permissions-Policy"] = "camera=(), microphone=(), geolocation=()"
response.headers["Strict-Transport-Security"] = "max-age=63072000; includeSubDomains; preload"
return response
وبالنسبة لـ CORS: إياك واستخدام allow_origins=["*"] مع allow_credentials=True! بل حدد النطاقات المصرح بها بدقة من خلال متغيرات البيئة.
الخلاصة
أمان واجهات البرمجة ليس إعداداً تفعله لمرة واحدة، بل هو انضباط مستمر في كتابة الكود: تحديد معدل ذكي مبني على حساسية المسار، ترشيح حازم للمدخلات والمخرجات، ورؤوس أمان صارمة تعزل التطبيق عن الاستغلال العشوائي.