نماذج التحكم بالوصول ومصفوفة الصلاحيات
كيف تنظّم الصلاحيات في نموذج واضح يدير الوصول للميزات والبيانات حسب دور المستخدم؟ ⏱ نحو 45 دقيقة.
- تقارن نماذج
ACLوRBACوABACوتختار المناسب. - تسمّي الصلاحيات بصيغة المورد:الفعل.
- تبني مصفوفة صلاحيات للأدوار والموارد مع شروط الملكية.
- تصمم نموذج بيانات
RBACبجداول الربط.
١ثلاثة نماذج للتحكم بالوصول
بعد تحليل الأدوار نحتاج نموذج صلاحيات Authorization Model: طريقة منظمة تقرر بها «هل يحق لهذا المستخدم هذا الفعل على هذا المورد؟». ثلاثة نماذج شائعة:
| النموذج | الفكرة | مثال | يناسب |
|---|---|---|---|
| ACL قائمة التحكم | لكل مورد قائمة بالمستخدمين المسموح لهم | ملف مشترك مع أشخاص بأسمائهم | مشاركة ملفات بين أفراد |
| RBAC حسب الدور | الصلاحيات تُعطى للأدوار، والمستخدمون يُسندون إلى أدوار | دور «موظفة تسجيل» يملك «اعتماد الطلبات» | أغلب أنظمة المؤسسات |
| ABAC حسب الخصائص | القرار بقاعدة على خصائص المستخدم والمورد والسياق | «المدرب يرى التسجيل إن كانت الدورة دورته» | قواعد دقيقة لا تكفيها الأدوار |
النموذج العملي لمعظم تطبيقات الويب: RBAC أساسًا، مع شروط ملكية قليلة (من ABAC) حيث يلزم. نصمم بهذه الطريقة في «دورات».
٢تسمية الصلاحيات
الصلاحية = فعل على مورد. تسميتها باتفاق ثابت المورد:الفعل تجعلها واضحة وقابلة للبحث والتدقيق:
| الصلاحية | معناها |
|---|---|
course:read | عرض الدورات |
course:create | إضافة دورة |
enrollment:create | إنشاء طلب تسجيل |
enrollment:read:own | عرض طلبات التسجيل الخاصة بالمستخدم فقط |
enrollment:approve | اعتماد طلب أو رفضه |
report:finance | عرض التقارير المالية |
user:manage | إدارة الحسابات وإسناد الأدوار |
٣مصفوفة الصلاحيات
مصفوفة الصلاحيات جدول واحد يلخص التصميم كله: الأدوار أعمدة، والصلاحيات صفوف. يقرؤها العميل ويعتمدها، ويبرمج منها المطور، ويختبر منها المختبِر:
| الصلاحية | زائر | متدرب | مدرب | تسجيل | مدير |
|---|---|---|---|---|---|
course:read | ✓ | ✓ | ✓ | ✓ | ✓ |
enrollment:create | ✗ | ✓ | ✗ | ✗ | ✗ |
enrollment:read | ✗ | الخاصة به | دوراته | ✓ | ✓ |
enrollment:approve | ✗ | ✗ | ✗ | ✓ | ✗ |
attendance:record | ✗ | ✗ | دوراته | ✗ | ✗ |
report:finance | ✗ | ✗ | ✗ | ✗ | ✓ |
user:manage | ✗ | ✗ | ✗ | ✗ | ✓ |
٤نموذج بيانات RBAC
لكي يحفظ النظام الأدوار والصلاحيات ويعدّلها المدير دون تغيير الكود، نصمم لها بيانات. المستخدم له دور أو أكثر، والدور يمنح صلاحية أو أكثر:
classDiagram class User["المستخدم"] { +int id +String email +can(String permission) bool } class Role["الدور"] { +int id +String name } class Permission["الصلاحية"] { +int id +String code } User "0..*" --> "1..*" Role : له Role "0..*" --> "1..*" Permission : يمنح
العلاقتان كثير إلى كثير: مستخدم بعدة أدوار، ودور لعدة مستخدمين. والعملية can(permission) هي ما يستدعيه الكود: «هل يملك هذا المستخدم الصلاحية عبر أي من أدواره؟».
وفي قاعدة البيانات تصبح كل علاقة كثير إلى كثير جدول ربط، كما تعلمنا في الدرس 9. هذا تحدي الدرس.
توقّع وتحقّق
في RBAC تُعطى الصلاحيات لـ:
«المدرب يرى التسجيل إن كانت الدورة دورته» قاعدة من نوع:
صيغة تسمية الصلاحيات المقترحة:
كيف تُحفظ علاقة الأدوار بالصلاحيات في قاعدة البيانات؟
الخلاصة
ACLقائمة لكل مورد، وRBACصلاحيات للأدوار، وABACقواعد على الخصائص.- العملي:
RBACأساسًا مع شروط ملكية حيث يلزم. - الصلاحية: مورد:فعل، مثل
enrollment:approve. - مصفوفة الصلاحيات: الأدوار × الصلاحيات، يعتمدها العميل ويبرمج منها المطور ويختبرها المختبِر.
- البيانات:
usersوrolesوpermissionsمع جدولي ربطuser_rolesوrole_permissions.
تحدٍّ تصميمي: جداول RBAC
متقدمصمّم مخطط الكيانات الذي يحفظ المستخدمين وأدوارهم وصلاحيات كل دور، بحيث يستطيع المدير تعديلها دون تغيير الكود.
- ثلاثة جداول أساسية: USERS و ROLES و PERMISSIONS، لكل منها PK.
- جدولا ربط: USER_ROLES (user_id و role_id) و ROLE_PERMISSIONS (role_id و permission_id) بمفاتيح أجنبية.
- كل جدول أساسي في علاقة «واحد إلى كثير» مع جدول الربط الخاص به.
- رمز الصلاحية code فريد UK.
- المخطط مكتوب بصيغة صحيحة ويُرسم
- نوعه: مخطط كيانات erDiagram
- جدول PERMISSIONS
- جدول USER_ROLES
- جدول ROLE_PERMISSIONS
- PERMISSIONS له PK
- رمز الصلاحية فريد
- USER_ROLES فيه user_id FK
- USER_ROLES فيه role_id FK
- ROLE_PERMISSIONS فيه permission_id FK
- USERS واحد ← USER_ROLES كثير
- ROLES واحد ← USER_ROLES كثير
- ROLES واحد ← ROLE_PERMISSIONS كثير
- PERMISSIONS واحد ← ROLE_PERMISSIONS كثير
💡 تلميح 1
💡 تلميح 2
USERS ||--o{ USER_ROLES : "له".💡 تلميح 3
string code UK.حاول بنفسك أولًا؛ للتصميم أكثر من حلّ صحيح، والفحص يتأكد من العناصر الأساسية فقط.
erDiagram USERS ||--o{ USER_ROLES : "له" ROLES ||--o{ USER_ROLES : "مسند إلى" ROLES ||--o{ ROLE_PERMISSIONS : "يمنح" PERMISSIONS ||--o{ ROLE_PERMISSIONS : "ضمن" USERS { int id PK string email UK } ROLES { int id PK string name UK } PERMISSIONS { int id PK string code UK } USER_ROLES { int user_id FK int role_id FK } ROLE_PERMISSIONS { int role_id FK int permission_id FK }