كيفية إضافة التحكم بالوصول القائم على الأدوار (RBAC) إلى تطبيقك
لإضافة التحكم بالوصول القائم على الأدوار، امنح كل مستخدم دوراً واحداً أو أكثر (مثل مدير أو محرر أو مشاهد)، وحدد الإجراءات التي يُسمح لكل دور بتنفيذها، ثم تحقق من هذه الصلاحيات على الخادم في كل طلب، لا عبر إخفاء الأزرار فقط. وتحقق أيضاً من أن السجل الذي يُصل إليه ينتمي إلى حساب المستخدم أو فريقه. ابدأ بعدد قليل من الأدوار الثابتة في قاعدة بياناتك، واختبر بمحاولة الوصول إلى بيانات مستخدم آخر مباشرة.
المصادقة مقابل التفويض
كلمتان كثيراً ما تختلطان:
- المصادقة (Authentication) تجيب عن من أنت؟ — تسجيل الدخول. انظر كيفية إضافة تسجيل الدخول إلى تطبيقك.
- التفويض (Authorisation) يجيب عن ماذا يُسمح لك أن تفعل؟ — أي الصفحات والسجلات والإجراءات يستطيع المستخدم المسجّل الدخول الوصول إليها.
التحكم القائم على الأدوار هو الطريقة الأكثر شيوعاً للتفويض. وهو مهم: اعتباراً من سبتمبر 2026، يحتل Broken Access Control المرتبة الأولى في قائمة OWASP Top 10:2025، وهي القائمة المستخدمة على نطاق واسع لأخطر مخاطر أمان تطبيقات الويب. ومن أكثر الأعطال شيوعاً أن يقرأ مستخدمون سجلات مستخدمين آخرين بتغيير معرّف في الرابط، أو أن يستدعي مستخدمون عاديون مسارات واجهة برمجية مخصصة للمديرين.
اختر نموذجاً
| النموذج | طريقة العمل | مناسب لـ | المفاضلة |
|---|---|---|---|
| عمود دور واحد | users.role = admin / member | التطبيقات الصغيرة ذات دورين أو ثلاثة | يصبح فوضوياً عندما يحتاج الناس إلى أدوار مختلفة في أماكن مختلفة |
| أدوار + صلاحيات | تُربط الأدوار بصلاحيات مسمّاة (invoices.approve)، ويتحقق الكود من الصلاحيات | التطبيقات التي ستنمو قواعدها | جداول أكثر؛ وقائمة صلاحيات تحتاج إلى صيانة |
| أدوار لكل فريق (متعدد المستأجرين) | جدول عضويات: مستخدم + منظمة + دور | SaaS حيث ينتمي الناس إلى فرق أو مساحات عمل | يجب أن يكون كل استعلام محصوراً في المنظمة |
| قائم على السمات أو العلاقات | قواعد على سمات السجل ("الكاتب يستطيع تعديل منشوره") أو على العلاقات (مشارك مع) | المستندات والمشاركة وسير العمل المعقد | أصعب في الفهم؛ فكّر في مكتبة أو خدمة مخصصة |
| أدوار من مزوّد المصادقة | مزوّد تسجيل الدخول يخزّن الأدوار أو عضويات المنظمات | التطبيقات التي تستخدم مزوّد مصادقة مستضافاً أصلاً | مرتبط بذلك المزوّد؛ ويجب أن تبقى الصلاحيات مفروضة على خادمك |
في الممارسة، تجمع معظم التطبيقات بين أمرين: الأدوار لتحديد نوع الإجراءات التي يستطيع الشخص القيام بها، والملكية لتحديد السجلات التي يستطيع تنفيذها عليها. فـ"المحررون يستطيعون تعديل المنشورات" قاعدة دور؛ أما "…المنشورات في مساحة عملهم" فقاعدة ملكية. وتحتاج إلى الاثنين.
ابدأ أبسط مما تظن. فالمدير والعضو والمشاهد تغطي عدداً مدهشاً من التطبيقات. ومن الأسهل تقسيم دور لاحقاً من التعامل مع عشرة أدوار لا يفهمها أحد.
صمّم الأدوار قبل كتابة الكود
اكتب جدول صلاحيات بلغة بسيطة أولاً. وهو يعمل كمواصفات للذكاء الاصطناعي، وكخطة اختبار لك في الوقت نفسه:
| الإجراء | المالك | المدير | العضو | المشاهد |
|---|---|---|---|---|
| عرض المشاريع في الفريق | ✓ | ✓ | ✓ | ✓ |
| إنشاء المشاريع وتعديلها | ✓ | ✓ | ✓ | |
| حذف المشاريع | ✓ | ✓ | ||
| دعوة الأشخاص وإزالتهم | ✓ | ✓ | ||
| تغيير الأدوار | ✓ | |||
| الفوترة | ✓ |
حدد الحالات الحدّية أيضاً: هل يستطيع المالك الأخير المغادرة؟ هل يستطيع المدير إزالة المالك؟ ماذا يرى المستخدم المُزال؟
خطوة بخطوة
1. ابدأ بتسجيل دخول يعمل أولاً
يقع التحكم القائم على الأدوار فوق المصادقة. يجب أن يعرف الخادم بثقة من يقدّم كل طلب، من جلسة أو رمز موثّق، ولا يعتمد أبداً على معرّف مستخدم يرسله المتصفح في جسم الطلب.
2. خزّن الأدوار في قاعدة البيانات
بالنسبة لتطبيق لفريق واحد، يكفي عمود role في جدول المستخدمين. أما للفرق فاستخدم جدول عضويات:
create table memberships (
user_id uuid references users(id),
organization_id uuid references organizations(id),
role text not null check (role in ('owner','admin','member','viewer')),
primary key (user_id, organization_id)
);
لا تدع المستخدمين يحددون أدوارهم بأنفسهم من خلال تحديث عادي للملف الشخصي. تمر تغييرات الأدوار عبر نقطة نهاية مخصصة تتحقق من الصلاحيات.
3. تحقق من الصلاحيات على الخادم، في مكان واحد
اكتب دالة مساعدة واحدة، شيئاً مثل can(user, 'projects.delete', project)، واستدعها في كل مسار واجهة برمجية، وكل إجراء على الخادم، وكل مهمة خلفية تقرأ البيانات أو تغيّرها. الدالة المركزية الواحدة أسهل في المراجعة والاختبار من فحوصات متناثرة في الكود. والرفض هو الافتراض: إذا لم تسمح أي قاعدة بالإجراء، يُرفض.
4. احصر كل استعلام
يجب أن يتضمن كل استعلام لبيانات الفريق الفريقَ نفسه: where organization_id = :currentOrg، لا where id = :id وحدها. وهذا ما يمنع شخصاً من تغيير /projects/123 إلى /projects/124 ورؤية مشروع شركة أخرى. أعد "غير موجود" بدلاً من "ممنوع" للسجلات التي تعود لفرق أخرى، حتى لا تكشف أنها موجودة.
5. أضف حماية على مستوى قاعدة البيانات حيثما يلزم
أمان مستوى الصف (Row-level security) في Postgres يتيح لقاعدة البيانات فرض الصفوف التي يستطيع كل مستخدم رؤيتها. وهو ضروري إذا كان المتصفح يتصل بقاعدة البيانات مباشرة (كما في بعض الخدمات الخلفية المستضافة)، وطبقة ثانية مفيدة للجداول الحساسة في الحالات الأخرى.
6. اعكس الأدوار في الواجهة
الآن أخفِ الإجراءات التي لا يستطيع المستخدمون تنفيذها أو عطّلها، حتى لا يبدو التطبيق مربكاً. وهذا من أجل سهولة الاستخدام فقط؛ فالفحوصات على الخادم هي التي تحمي فعلاً.
7. سجّل الإجراءات الحساسة
سجّل من غيّر الأدوار، أو حذف البيانات، أو صدّر السجلات، ومتى. يساعد سجل التدقيق في الإجابة عن أسئلة الدعم والحوادث.
8. اختبر كما يفعل المهاجم
سجّل الدخول بكل دور وجرّب كل إجراء في جدول الصلاحيات. ثم جرّب الأشياء التي يجب ألا تنجح: استدعاء مسارات واجهة المدير بدور مشاهد، وتغيير المعرّفات في الروابط والطلبات، وإزالة نفسك كمالك أخير. تستحق الاختبارات الآلية لجدول الصلاحيات أن تُكتب مرة واحدة بعد استقرار القواعد.
مطالبات تنجح
أضف التحكم بالوصول القائم على الأدوار. أدوار لكل منظمة: مالك، ومدير، وعضو، ومشاهد، تُخزَّن في جدول memberships. الصلاحيات موجودة في هذا الجدول: [الصق جدولك]. أنشئ دالة مساعدة واحدة على الخادم can(user, action, resource)، ترفض افتراضياً، واستخدمها في كل مسار واجهة برمجية. احصر كل استعلام بـ organization_id. أخفِ الإجراءات التي لا يستطيع المستخدم تنفيذها في الواجهة، لكن لا تعتمد على ذلك أبداً من أجل الأمان.
راجع كل مسار واجهة برمجية ودالة خادم في هذا التطبيق. لكل منها اذكر البيانات التي تقرأها أو تغيّرها، وهل تتحقق من أن المستخدم مسجّل الدخول، وهل تتحقق من دوره، وهل تحصر الاستعلام بمنظمته. أصلح أي فحص مفقود، وأرِني القائمة.
أضف صفحة /admin خاصة بالمديرين فقط حيث يستطيع المالك تغيير أدوار الأعضاء. امنع إزالة المالك الأخير أو تخفيض رتبته، وسجّل كل تغيير في الدور مع من قام به ومتى، وتأكد من أن نقطة نهاية تغيير الأدوار ترفض أي شخص ليس مالكاً.
أخطاء شائعة
- التحقق من الأدوار في الواجهة الأمامية فقط. تبقى الواجهة البرمجية مفتوحة لأي شخص يستدعيها.
- الثقة في المعرّفات القادمة من العميل، مثل
userIdأوroleفي جسم الطلب بدلاً من الجلسة. - استعلامات غير محصورة تجلب السجل بمعرّفه وحده.
- التحقق من الأدوار في الصفحات دون مسارات الواجهة البرمجية، أو عمليات التصدير، أو تنزيل الملفات، أو الـ webhooks.
- المدير بحسب عنوان بريد إلكتروني مكتوب في الكود (
if email === 'me@...')، وهذا سهل النسيان وصعب التغيير. - أدوار كثيرة مبكراً جداً، لا يستطيع أحد تفسيرها بعد ستة أشهر.
- جلسات قديمة: المستخدم الذي خُفّضت رتبته يحتفظ بصلاحيات المدير حتى يسجّل الخروج. تحقق من الأدوار من قاعدة البيانات، أو حدّثها، عند الإجراءات الحساسة.
قائمة التحقق لـ RBAC
- جدول الصلاحيات مكتوب بلغة بسيطة، والحالات الحدّية محسومة
- يعرف الخادم المستخدم من الجلسة، لا من بيانات الطلب
- الأدوار مخزّنة في قاعدة البيانات؛ ولا يستطيع المستخدمون تغيير أدوارهم بأنفسهم
- فحص صلاحيات مركزي واحد، يرفض افتراضياً، ويُستخدم في كل مسار
- كل استعلام محصور بمنظمة المستخدم أو ملكيته
- أمان مستوى الصف حيث يستطيع المتصفح الوصول إلى قاعدة البيانات
- الواجهة تخفي ما لا يستطيع المستخدمون فعله (لسهولة الاستخدام فقط)
- الإجراءات الحساسة مسجّلة
- كل دور مختبر، بما في ذلك استدعاءات الواجهة البرمجية المباشرة والمعرّفات المتغيرة
التحكم بالوصول بند واحد في قائمة أطول؛ وتغطي قائمة فحص الأمان للتطبيقات المبنية بالذكاء الاصطناعي الباقي. وإذا كنت تبني أداة لموظفيك الداخليين، فإن كيفية بناء أداة داخلية يوضح أين تقع الأدوار.
RBAC في Mythex
لا يوفر Mythex نظام تسجيل دخول أو أدوار مدمجاً لمستخدمي تطبيقك. تختار مكتبة أو مزوّد مصادقة وتصف الأدوار، ويربطها الوكيل بالكود وبقاعدة بيانات Postgres لمشروعك (إضافة تسجيل الدخول إلى تطبيقك). أما أدوار مساحة عمل Mythex نفسها، مثل المالك والعضو، فهي تتحكم في من يستطيع تعديل مشاريعك في Mythex، لا في من يستطيع استخدام التطبيق الذي تنشره. استخدم وضع التخطيط (Plan mode) للاتفاق على جدول الصلاحيات قبل البناء، ثم استخدم مطالبة المراجعة أعلاه، واختبر كل دور في المعاينة قبل النشر. ومطالبات الأمان في الوثائق متابعة مفيدة.
الأسئلة
ما هو التحكم بالوصول القائم على الأدوار؟
التحكم بالوصول القائم على الأدوار (RBAC) يحدد ما يستطيع كل مستخدم فعله بناءً على الأدوار التي يحملها، مثل مدير أو محرر أو مشاهد. تُربط الصلاحيات بالأدوار لا بالأفراد، لذا يصبح تغيير ما يستطيع شخص فعله مجرد تغيير لدوره.
ما الفرق بين المصادقة والتفويض؟
المصادقة (Authentication) تتحقق من هوية الشخص، عادةً عبر تسجيل الدخول. أما التفويض (Authorisation) فيحدد ما يُسمح لذلك الشخص المسجّل الدخول برؤيته وفعله. والتحكم القائم على الأدوار (RBAC) طريقة واحدة لتنفيذ التفويض.
هل يكفي إخفاء الأزرار في الواجهة لتقييد الوصول؟
لا. يستطيع أي شخص استدعاء واجهتك البرمجية مباشرة، لذا إخفاء الزر يغيّر فقط ما يراه الناس. يجب التحقق من كل طلب يقرأ البيانات أو يغيّرها على الخادم، بحسب دور المستخدم وملكيته للسجل.
هل يجب أن أستخدم أمان الصفوف (Row-level security) في Postgres؟
أمان مستوى الصف يتيح لقاعدة البيانات نفسها فرض الصفوف التي يستطيع كل مستخدم قراءتها أو كتابتها، وهي شبكة أمان قوية، خاصة عندما تتصل الواجهة الأمامية بقاعدة البيانات مباشرة. لكنه يضيف تعقيداً، لذلك تفرض كثير من التطبيقات الصلاحيات في كود الخادم، وتستخدم أمان الصفوف كطبقة إضافية للجداول الحساسة.