الصلاحيات بطريقة بسيطة وفعّالة في أنظمة الصلاحيات المُعقدة

السلام عليكم ورحمة الله وبركاته

أعمل على نظام وأحتجت عدد كبير من الصلاحيات لتوزيعها على مُستخدمي النظام، أنظمة الصلاحيات بإستخدام الجداول مُكلفة وتستهلك وقت وجُهد، إتجهت لإستخدام النظام الثنائي لإعتماده في هذه النظام لسهولة التعامل مع الصلاحيات من خلاله ولكنه لم يفي بالغرض فحدود التعامل بالنظام الثنائي هو العدد 2 مرفوع لقوة 62 في لغة php وبهذا سأكون محدود بهذا الرقم كحد أقصى للصلاحيات المُتاحة بالمكتبات الإفتراضية للغة، ابتعدت عن فكرة استخدام النظام الثنائي وإتجهت لاستخدام السلاسل النصية بنفس مبدأ شبية في المُستخدم في النظام الثنائي.

  • فلنفرض أن لدينا 30 صلاحية سيتم تمثيل تلك الصلاحيات كسلسة نصية مكونة من الصفر والواحد كالتالي:

    001100000011101010010100110000

الصفر يرمز لعدم تمكين الصلاحية والواحد يرمز لتمكين الصلاحية

  • ستكون لدينا مصفوفة باسماء الصلاحيات المطلوبة -ويمكنك زيادتها او انقاصها دون تاثير على سير العملية- مفتاح كل قيمة في المصفوفة للصلاحية يناظرة مفتاح لقيمة الصلاحية في السلسة النصية، وعلى هذا يُمكننا بسهولة إعطاء ونزع الصلاحيات للمُستخدمين بسلاسة ولأي عدد من الصلاحيات بتغيير قيمة السلسة النصية على حسب الصلاحيات بما يُناظر كل صلاحية في المصفوفة.

التالي فئة بلغة php لتنفيذ هذه الطريقة -يمكنك تنفيذ الطريقة باللغة التي تُفضلها-:

<?php
class permissions
{
    // مصفوفة لتخزين اسماء الصلاحيات التي ستُستخدم
    private $permissions = [];

    // باني الفئة
    public function __construct()
    {
        // مصفوفة بجميع الصلاحيات المُتاحة
        // عينة من بعض الصلاحيات لنظام ما
        $this->permissions = [  'carAdd','carEdit','carDelete','carEditName','carEditModel','carEditPower',
                                'carEditPrice','carEditColor','carEditCompany','carEditCurancy','carEditMotor',
                                'motoAdd','motoEdit','motoDelete','motoEditName','motoEditModel','motoEditPower',
                                'motoEditPrice','motoEditColor','motoEditCompany','motoEditCurancy','motoEditMotor',
                                ];
    }
    // دالة اختبار الصلاحية
    // تقوم الدالة بإختبار الصلاحية المُممرة للدالة على المُستخدم النشط
    // تعيد الدالة القيمة الصحيحة في حال كان المُستخدم يمتلك تلك الصلاحية
    // تعيد الدالة القيمة الخاطئة في حال كان المُستخدم النشط لا يملك تلك الصلاحية
    public function permission($permissionName)
    {
        if(!in_array($permissionName, $this->permissions))
            return false;

        $userPermissions = $this->getUserPermissons();
        $key = $this->key($permissionName);
        if(!isset($userPermissions[$key]) || $userPermissions[$key] != 1)
            return false;
        else
            return true;
    }

    // دالة إضافة صلاحيات مُستخدم جديد
    // تكون الصلاحيات عبارة عن صناديق اختيار بنفس اسماء الصلاحيات للتحقق منها
    // تقوم الدالة بإعادة سلسة نصية مكونة من الصفر والواحد عبارة عن صلاحيات المُستخدم الجديد
    private function addPermissions()
    {
        $userPermissions = str_pad('', count($this->permissions), '0');

        foreach($this->permissions as $value){
            if(isset($_POST[$value])){
                $userPermissions[$this->key($value)] = 1;
            }
        }
        return $userPermissions;
    }

    // دالة تعديل صلاحيات مُستخدم موجود
    // تكون الصلاحيات عبارة عن صناديق اختيار بنفس اسماء الصلاحيات للتحقق منها
    // تقوم الدالة بإعادة سلسة نصية مكونة من الصفر والواحد بعد تعديل صلاحيات المُستخدم
    // يتم تخزين سلسة الصلاحيات الجديدة للمُستخدم في قاعدة البيانات أو أي وحدة تخزين أُخرى
    private function editPermissions($userPermissions)
    {
        $userPermissions = str_pad($userPermissions, count($this->permissions), '0');

        foreach($this->permissions as $value){
            if(isset($_POST[$value]))
                $userPermissions[$this->key($value)] = 1;
            else
                $userPermissions[$this->key($value)] = 0;
        }
        return $userPermissions;
    }


    // تقوم هذه الدالة بإعادة صلاحيات المُستخدم النشط كسلسة نصية
    // تكون هذه السلسة مُخزنة كقيمة في جدول المُستخدمين ولكل مُستخدم سلسة نصية شبية بالتالية
    public function getUserPermissons()
    {
        return '0001101011110001000111';
    }

    // دالة لإعادة مفتاح القيمة في المصفوفة
    private function key($value)
    {
        return array_search($value, $this->permissions);
    }
}


$perm = new permissions();

// للتحقق من الصلاحية
if($perm->permission('carAdd'))
    echo "can add car";
else
    echo "can't add car";

السلام عليكم ورحمة الله وبركاته

اخي الكريم

جميلة هذه الطريقة .. لكنها ليست عملية اضافة الى انها ليست احترافية على المدى البعيد وسوف تواجه مشاكل مستقبلية عندما تحتاج الى التطوير واعادة البناء وما شابه ذلك ..

عموما انصحك بان تبدأ القرأة بعمق في هذه المصطلحات RBAC and ABAC يجب ان تستوعبها جيدا وتعرف الفروقات بينها ومستوياتها ثم تبدا في عملية وضع التصورات وتطويرها وفق هذا المبدأ العالمي ..

https://en.wikipedia.org/wi...

and

https://en.wikipedia.org/wi...

بالنسبة لكثرة الجداول لا باس ليست مشكلة يمكن حلها ببساطة بالانتقال الى NOSQL مثل MongoDB

لكن يجب ان تحذر فهذا عالم جديد وجميل من قواعد البيانات له شروط وضوابط وهو اسرع بمئات المرات من قواعد البيانات العادية RDBMS وسوف تودي نفس الطريقة التي تسعى لها لكن "كون على حذر" الموضوع ليس معقدا ولكنه جديد كليا طبعا يستخدم مبدأ json في التخزين لكن بطريقة اكثر متعة

حاول ان تبدا بطرق علمية وتقرا وتصل الى مصطلحات موثقة لكي لا تخسر وقتك في التعلم وتبني نفسك بناء قوي يساعدك في التنقل والتوسع بشكل احترافي

وفقك الله اخي المناضل :)

اطلعت سريعاً على الروابط، فهي تتحدث عن كيفية بناء أنظمة الصلاحيات المُتعددة أو الشكل الذي يُفترض أن يتم بناء النظام به، ولكني في موضوعي أتطرق لكيفية تطبيق أنظمة الصلاحيات بشكل مُبسط، فيُمكن تطبيق مبدأ الـ ABAC باستخدام الطريقة أعلاه، ولا يُشترط الالتزام بها دوماً فعلى سبيل المثال: في النظام الذي أعمل عليه عدد الصلاحيات أكبر بكثير من عدد مُستخدمي النظام، فعدد مُستخدمي النظام لا يتجاوزو العشرة أي تنفيذ نظام الأدوار لمنح الصلاحيات لن يكون ذو أهمية بالنسبة لهذا العدد الصغير من المُسنخدمين، ولكن نظام الأدوار سيكون فعال أكثر في حال كان هناك عدد كبير من المُستخدمين للنظام فلا يُعقل أن يتم وضع صلاحيات لكل مُستخدم على حده.

سعدت بمداخلتك حقًا واستفدت من الروابط أعلاه

اخي الكريم .. ارجو ان يتسع صدرك لي فنحن في الاخير نسعى الى هدف واحد وهو الوصول الى الطريقة الافضل "بدون الخروج عن النسق الافتراضي المتعارف به"

نعم ما احلتك الية نظام ادارة صلاحيات على مستوى المستخدمين لكنه اخي الكريم نظام عالمي يعمل يه حتى في البناء البرمجي على مستوى user model مثال منظومة ساب او منظومة اوركل او منظومة ميكروسوفت او منظومة قوقل آب ... جميعها تستخدم هذا المنهج في بناء برامجها لكي لا ترهق نفسها اولا في الاندماج مع البرامج الاخرى .. ثانيا وهو الاهم لكي يتم توحيد ترحيل الصلاحيات من انظمة التشغيل في حالة وجودها ( LDAP or AD ) ليس شرطا هنا ان يكون جميع المستخدمين متواجدين بل لكي لا يصبح هناك اعمال اضافية في التكامل بين ادارة المستخدمين من نظام الى اخر وعدم التعارض بينها وعدم التكرار والتضارب في الصلاحيات مما يسبب ثغرات غير مرئية ..

اخي الكريم ان ما اتحدث به هنا ليس نظام صلاحيات تابع لانظمة التشغيل انا اتحدث هنا عن مفهوم بناء متقدم جدا يمكن توسيعه الى حدود اكثر بكثير مما وصلت اليه "بكثير جدا" وفي نفس الوقت مرهق في الاحاطة البرمجية كمنظومة ديناميكية

انظر الى استخدام هذا المفهوم بلغة PHP ..

استخدام المفهوم عبر .Net وهو هنا في حده الادنى طبعا ..

ثم اتي الى رسالتك الاخيرة والتي لاحظت فيها وقد اكون مخطأ استخفاف بمفهوم NOSQL انصحك ان تقراء بعمق في هذ المجال فانت تحرم نفسك شي لا يمكن تصوره من التقدم التقني الهائل على مستوى معالجة البيانات والسرعة والقوة .. ولكي اكون اكثر وضوحا (linkdin, google , NASA ) وغيرهم الكثير يعمل بها الان في منتجات كثيرة وجاري النقل اليها في فيس بوك رغم ان الموضوع يحتاج الى حلول في مستوى العلاقات الاكثر تعقيدا .. لكن فرق السرعة تجاوز الـــ ٥ اضعاف للداتا الضخمة ، ايضا ساب تعمل عليها وIBM انتقلت اليها فعلا على نظاق النظم التحتية ..

الخلاصة انت الان تريد حل مشكلة التخلص من عدة جداول ولا تريد الدخول في هذا الرعب من الاستعلامات والتي يطلق عليها Nested SQL

http://mikehillyer.com/arti...

ارجو ان لا تكون قد وضعت في موقف السيرفر يكون Down بسبب SQL وان شاء الله ما تصير معاك ..

وكلما تضخمت الداتا زاد الثقل على cache and buffer، واصبح الموضوع اعقد والوقت اطول والاستعلام اكثر ارهاق للعتاد .. لذلك الNSQL .. لا يوجد لديه مشكله نهائي في هذا الموضوع وكانك تتحكم في بيانات عادية رغم ضخامتها وتشعبها وكميتها المهولة ..

اعتذر احاول دائما التوجية الى مصادر وليس التنظير فقط .. :)

تُسعدني كثيرًا النقاشات التقنية، لا تتوقف :)

لم نختلف فأنا أتفهم أن ما أحلتني إليه مفهوم لبناء أنظمة صلاحيات بشكل مُتماسك قابل لإعادة الاستخدام والتوسع، الطريقة التي في الأعلى ما هي طريقة بسيطة يُمكن استخدامها في أنظمة الصلاحيات أي كان هذا المفهوم، فأنا هنا لا أتطرق للمفهوم ولكن لوسيلة لتطبيق المفهوم كاستخدام قواعد البيانات NoSQL بدلاً من SQL لتطبيق أحد مفاهيم بناء أنظمة الصلاحيات، وإليك تطبيق لمفهوم الـ RBAC باستخدام الطريقة التي تحدثت عنها في الأعلى:

  • ملاحظة: لم أقم بتجربة وتنقيح الكود، سأقوم بذلك عند العودة للمنزل، يُمكن إعتباره حاليًا pseudo code

ثم اتي الى رسالتك الاخيرة والتي لاحظت فيها وقد اكون مخطأ استخفاف بمفهوم NOSQL

لا أعلم ما الذي قلته في حقها ليصلك هذا الشعور :) لقد عملت على Mongodb منذ مدة ومن المُعجبين بها ولكن لم أنُشيء مشروع فعلي مبني عليها بعد.

لا افهم ما حاجتك لصلاحيات بحجم ما ذكرت في مقالك الاول ، 30 صلاحية ؟ لكل مستخدم نفس العدد من الصلاحيات ؟

إتجهت لإستخدام النظام الثنائي لإعتماده في هذه النظام لسهولة التعامل مع الصلاحيات من خلاله ولكنه لم يفي بالغرض فحدود التعامل بالنظام الثنائي هو العدد 2 مرفوع لقوة 62 في لغة php وبهذا سأكون محدود بهذا الرقم كحد أقصى للصلاحيات المُتاحة بالمكتبات الإفتراضية للغة، ابتعدتعن فكرة استخدام النظام الثنائي وإتجهت لاستخدام السلاسل النصية بنفس مبدأ شبية في المُستخدم في النظام الثنائي

ما نوع الصلاحيات التي تحتاج الى كل هذا الزخم من الصلاحيات .. حتى الصلاحيات العميقة التي تصل الى مستوى الحقول في السجلات والمنبثقة من مميزات منبثقة من مكونات رئيسية وتكون تحت مظلة عامة لصلاحيات البرنامج لا تصل الى ان تكون بهذا التعقيد المتعمد !؟

هل تستطيع ان تفهمني ماذا تريد بالضبط ولو برسالة على الخاص اذا كان موضوعك خاص طبعا

النظام لإدارة شركة تشتمل على عدة أقسام سأذكر منها القسم خاص بإدارة السيارات، لدينا جدول لبيانات السيارات عبارة عن 23 حقل لكل سيارة، بحاجة لوضع صلاحيات (وصول/تعديل/عمليات خاصة) على كل حقل من تلك الحقول الخاصة بالسيارة.

عمليات خاصة: كتعديل قيمة حقل من قيمة معينة لأخرى.

بالإضافة لأقسام أُخرى بتفرعاتها، يتم منح صلاحيات مُعينة لعدد قليل من مُستخدمي النظام ككل على مستوى جميع الأقسام، وعليه سيكون لكل مُستخدم مجموعة صلاحيات مُختلفة عن الأخر وهذا ما دعاني لعدم استخدام أنظمة توزيع الصلاحيات على الأدوار ومن ثَم توزيع الأدوار على المُستخدمين.

كما توقعت صلاحيات على مستوى الحقول .. رائع جدا انك وصلت الى هذا المستوى في تطبيق فعلي "رائع بكل معنى الكلمة"

الان عليك ان تعمل بجهد كبير لبناء بنيتك بشكل اكاديمي .. طريقتك ليست عملية لانه سوف تحتاج مترجم وسيطلتحويل الصلاحيات الى سلسلة نصية والعكس بين برنامجك واي برنامج اخر سوف تضيفه مستقبلا .. والمشكلة الاكبر لو هناك من سيكمل على برنامجك ! ..

احاول تخيل processعند تعديل الصلاحيات !!!!! او خطأ في الصلاحيات كيف سيكون التتبع والمعالجة !!!!! يارب سترك :)

اضافة الى انك تعتمد 0 - 1 لكل حقل .. وتسنده ايضا لمثلها ان كان اب او ابن .. وتسندها الى ما هو اعلى Modul .. ثم الى ما هو اعلى وهكذا !!؟؟

يعني حتشتغل بلوكات ثابتة .. الى بلوكات ثابته اخرى اعلى .. الى بلوكات ثابته اخرى !!!

الموضوع هنا انك تشتت نفسك اكثر من اللازم .. هذا رائيي

لماذا تضيف جهد وسيط بينما يمكنك الاستعانة بعمل procedure mysql او view .. بحيث يكون الطلب دائما من جدول واحد فقط !!

طبعا الموضوع جميل ولكن مرهق في التأسيس .. انصحك ببنائه على المدى البعيد لجميع برامجك

نحن عملنا على هذا النوع من الصلاحيات ولكن بشكل اكبر بكثير (( تخيل هذا الموضوع الذي امامك الان ))

http://blog.orbitone.com/po...

يمكننا التواصل على سكايب اذا احببت اخي الكريم fsaedy

الان عليك ان تعمل بجهد كبير لبناء بنيتك بشكل اكاديمي .. طريقتك ليست عملية لانه سوف تحتاج مترجم وسيطلتحويل الصلاحيات الى سلسلة نصية والعكس بين برنامجك واي برنامج اخر سوف تضيفه مستقبلا .. والمشكلة الاكبر لو هناك من سيكمل على برنامجك ! ..

بالفعل لم أفكر في مسألة تكامل النظام مع أي برمجيات أُخرى، بالنسبة لعمل أحد على المشروع ففي هذه الحالة عليه تتبع عمل الكود خطوة خطوة :)

احاول تخيل processعند تعديل الصلاحيات !!!!! او خطأ في الصلاحيات كيف سيكون التتبع والمعالجة !!!!! يارب سترك :)

اضافة الى انك تعتمد 0 - 1 لكل حقل .. وتسنده ايضا لمثلها ان كان اب او ابن .. وتسندها الى ما هو اعلى Modul .. ثم الى ما هو اعلى وهكذا !!؟؟

يعني حتشتغل بلوكات ثابتة .. الى بلوكات ثابته اخرى اعلى .. الى بلوكات ثابته اخرى !!!

حقيقًا لا اعلم الكيفية التى وصلتك في الطريقة التي اتبعها أعلاه ولكن سأحاول توضيحها بشكل أفضل.

الشكل الذي استخدمه حاليًا كالتالي:

permissons
    add edit delete view change

users
    ahmed:      11111
    mohamed:    11011
    khaled:     00010
  • فأنا أعتمد على عدد الصلاحيات وترتيبهم، فعدد الصلاحيات يعني طول سلسة الصلاحيات وموضع الصلاحية هو قيمتها سواء 0 أو 1 في السلسة النصية، في حالة تعديل الصلاحية سيتم التعرف على موضع الصلاحية في السلسة النصية من خلال موضعها في مصفوفة الصلاحيات ليتم تعديل قيمتها. والشكل الذي وضعته في الرد

    سيكون على النحو:

    permissions
        add edit delete view change
    
    Rouls
        super_admin 11111
        admin       11011
        editor      01011
        writer      10011
        viewer      00010
        user        00011
        vistor      00000
    
    users
        ahmed: super_admin
        mohamed: admin
        khaled: editor, writer
    

وبالتالي عمليات تعديل الصلاحيات تكون على مستوى الدور

بإذن الله سأقوم بلإستخدام الطريقة مع أنظمة مُعقدة كالتي أحلتني إليها لأرى مدى أدائها، مع توفير واجهة للتعامل معها.

ملاحظة: هذا الرد كنت أكتب به قبل مُكالمتك، فوجدت أنه سيكون به بعض الإيضاح للفكرة أعلاه فتركته :)