Menu Permissions
نبدأ بتقديم مثال على Spring Boot يتضمن نظام قائمة. هذا المثال يستخدم jCasbin لإدارة صلاحيات القائمة. في النهاية، يهدف إلى تجريد وسيط برمجي، خصيصًا لصلاحيات القائمة، والذي يمكن توسيعه للغات أخرى يدعمها Casbin، مثل Go و Python.
1. ملفات التكوين
تحتاج إلى إعداد إدارة الأدوار والصلاحيات في ملف policy.csv، بالإضافة إلى العلاقات الأبوية-الفرعية بين عناصر القائمة. لمزيد من التفاصيل، يرجى الرجوع إلى هذا المستودع على GitHub.
1.1 نظرة عامة
باستخدام policy.csv، يمكنك تكوين صلاحيات الأدوار وهياكل القائمة بشكل مرن للتحكم الدقيق في الوصول. يحدد ملف التكوين هذا صلاحيات الوصول للأدوار المختلفة على عناصر القائمة المتنوعة، والعلاقات بين المستخدمين والأدوار، والعلاقات الهرمية بين عناصر القائمة.
1.2 تعريفات الصلاحيات (السياسات)
- قواعد السياسة: تُعرف السياسات ببادئة
p، محددة الأدوار (sub) وصلاحياتها (act) على عناصر القائمة (obj)، بالإضافة إلى تأثير القاعدة (eft)، حيث يشيرallowإلى أن الصلاحية ممنوحة، وdenyيشير إلى أنها مرفوضة.
أمثلة:
p, ROLE_ROOT, SystemMenu, read, allowتعني أن الدورROLE_ROOTلديه صلاحية القراءة لعنصر القائمةSystemMenu.p, ROLE_ROOT, UserMenu, read, denyتعني أن الدورROLE_ROOTمرفوض منه صلاحية القراءة لعنصر القائمةUserMenu.
1.3 الأدوار وعلاقات المستخدمين
- وراثة الدور: تُعرف علاقات المستخدم-الدور والتسلسل الهرمي للأدوار ببادئة
g. هذا يسمح للمستخدمين بوراثة الصلاحيات من دور واحد أو أكثر.
أمثلة:
g, user, ROLE_USERتعني أن المستخدمuserمُعين للدورROLE_USER.g, ROLE_ADMIN, ROLE_USERتعني أنROLE_ADMINيرث الصلاحيات منROLE_USER.
1.4 هرمية عناصر القائمة
- علاقات القائمة: تُعرف العلاقات الأبوية-الفرعية بين عناصر القائمة ببادئة
g2، مما يساعد في بناء هيكل القائمة.
أمثلة:
g2, UserSubMenu_allow, UserMenuتشير إلى أنUserSubMenu_allowهو قائمة فرعية لـUserMenu.g2, (NULL), SystemMenuتشير إلى أنSystemMenuليس لديها عنصر قائمة فرعي، أي أنها عنصر قائمة رئيسي.
1.5 وراثة صلاحيات القائمة والقواعد الافتراضية
عند إدارة صلاحيات القائمة مع jCasbin، تتبع العلاقة بين القوائم الأبوية والفرعية قواعد وراثة محددة، مع قاعدتين افتراضيتين مهمتين:
وراثة صلاحيات القائمة الأبوية:
إذا تم منح القائمة الأبوية صلاحية allow بشكل صريح، فإن جميع القوائم الفرعية تفترض افتراضيًا صلاحية allow ما لم يتم تحديدها بشكل صريح كـ deny. هذا يعني أنه بمجرد أن تكون القائمة الأبوية قابلة للوصول، فإن القوائم الفرعية تكون قابلة للوصول افتراضيًا.
التعامل مع القوائم الأبوية بدون إعدادات صلاحية مباشرة:
إذا لم تكن القائمة الأبوية لديها إعدادات صلاحية مباشرة (لا يُسمح بها صراحةً ولا يُرفض بها صراحةً) ولكن لديها قائمة فرعية واحدة على الأقل منحت صلاحية allow بشكل صريح، فإن القائمة الأبوية تُعتبر ضمنيًا لديها صلاحية allow. هذا يضمن أن المستخدمين يمكنهم التنقل إلى هذه القوائم الفرعية.
1.6 قواعد وراثة الصلاحيات الخاصة
فيما يتعلق بوراثة الصلاحيات بين الأدوار، وخاصة في السيناريوهات التي تتضمن صلاحيات deny، يجب اتباع القواعد التالية لضمان أمان النظام والتحكم الدقيق في الصلاحيات:
التمييز بين الرفض الصريح والافتراضي:
إذا تم رفض دور ما، مثل ROLE_ADMIN، بشكل صريح من الوصول إلى عنصر قائمة، مثل AdminSubMenu_deny (مُعلم كـ deny)، فإنه حتى إذا تم وراثة هذا الدور من قبل دور آخر (مثل ROLE_ROOT)، فإن الدور الوريث لا يُسمح له بالوصول إلى عنصر القائمة المرفوض. هذا يضمن ألا تتم تجاوز السياسات الأمنية الصريحة بسبب وراثة الدور.
وراثة صلاحيات الرفض الافتراضية:
على العكس من ذلك، إذا كان رفض دور للوصول إلى عنصر قائمة (مثل UserSubMenu_deny) هو افتراضي (لم يُعلم صراحةً كـ deny، ولكن لأنه لم يُمنح صراحةً صلاحية allow)، فعندما يُورث هذا الدور من قبل دور آخر (مثل ROLE_ADMIN)، يمكن للدور الوريث تجاوز حالة الرفض الافتراضية، مما يسمح بالوصول إلى هذه العناصر في القائمة.
1.7 وصف المثال
policy:
p, ROLE_ROOT, SystemMenu, read, allow
p, ROLE_ROOT, AdminMenu, read, allow
p, ROLE_ROOT, UserMenu, read, deny
p, ROLE_ADMIN, UserMenu, read, allow
p, ROLE_ADMIN, AdminMenu, read, allow
p, ROLE_ADMIN, AdminSubMenu_deny, read, deny
p, ROLE_USER, UserSubMenu_allow, read, allow
g, user, ROLE_USER
g, admin, ROLE_ADMIN
g, root, ROLE_ROOT
g, ROLE_ADMIN, ROLE_USER
g2, UserSubMenu_allow, UserMenu
g2, UserSubMenu_deny, UserMenu
g2, UserSubSubMenu, UserSubMenu_allow
g2, AdminSubMenu_allow, AdminMenu
g2, AdminSubMenu_deny, AdminMenu
g2, (NULL), SystemMenu
| MenuName | ROLE_ROOT | ROLE_ADMIN | ROLE_USER |
|---|---|---|---|
| SystemMenu | ✅ | ❌ | ❌ |
| UserMenu | ❌ | ✅ | ❌ |
| UserSubMenu_allow | ❌ | ✅ | ✅ |
| UserSubSubMenu | ❌ | ✅ | ✅ |
| UserSubMenu_deny | ❌ | ✅ | ❌ |
| AdminMenu | ✅ | ✅ | ❌ |
| AdminSubMenu_allow | ✅ | ✅ | ❌ |
| AdminSubMenu_deny | ✅ | ❌ | ❌ |
2. تحكم بأذونات القائمة
يمكن تحديد قائمة جميع عناصر القائمة التي يمكن الوصول إليها بواسطة اسم مستخدم معين من خلال الدالة findAccessibleMenus() المتاحة في MenuService. للتحقق مما إذا كان لدى مستخدم معين الحقوق للوصول إلى عنصر قائمة محدد، يمكن استخدام طريقة checkMenuAccess(). هذا النهج يضمن أن أذونات القائمة يتم التحكم بها بفعالية، مستفيدة من قدرات jCasbin لإدارة حقوق الوصول بكفاءة.