จัดการสิทธิ์การเข้าถึงด้วย Role Base Access Control (RBAC) แบบใช้ฐานข้อมูล

คู่มือการเรียนรู้ Yii Framework 2 (Yii2)

บทเรียนดีๆ สำหรับผู้ที่ต้องการแบ่งปัน บทเรียนของคุณอาจมีค่าสำหรับอีกหลายๆ คน

beta version

จัดการสิทธิ์การเข้าถึงด้วย Role Base Access Control (RBAC) แบบใช้ฐานข้อมูล

มานพ กองอุ่น yii2 rbac 5,896

สำหรับ Role Base Access Control หรือ RBAC นั้นเป็นการจัดการสิทธิ์การเข้าถึง Action ต่างๆ คล้ายกันกับการใช้งาน Access Control Filter แต่มีความแตกต่างเพิ่มเติมคือ

  • ผู้ใช้งานหนึ่งคนสามารถมีหลายบทบาทได้ เช่น บทบาทเป็น admin ของ ระบบ A แต่เป็น user ของระบบ B เป็นต้น


ใน Yii2 นั้นสามารถเก็บแบบ PHP ไฟล์ หรือเก็บแบบตารางในฐานข้อมูลก็ได้ สามารถดูรายละเอียดเพิ่มเติมได้ที่เว็บไซต์ของ Yii Framework เรื่อง Role Base Access Control (RBAC) (http://www.yiiframework.com/doc-2.0/guide-security-authorization.html) 
สำหรับตัวอย่างนี้จะใช้การเก็บข้อมูลในตารางฐานข้อมูล และใช้ Yii2 Advanced Application Template และกำหนดการใช้งานผ่าน console โดยมีวิธีการกำหนดดังนี้

การตั้งค่าเพื่อเรียกใช้ RBAC ในส่วน Component

เป็นการกำหนด authManager เพื่อเรียกใช้งาน DbManager ใน Web Application โดยกำหนดที่ไฟล์ common/config/main.php 

return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\DbManager',
        ],
        // ...
    ],
];

การ Migrate โครงสร้าง RBAC

ทำการ Migrate โครงสร้างตารางเก็บข้อมูล RBAC โดยเรียกใช้งาน Migrate Path โดยใช้คำสั่งดังต่อไปนี้

yii migrate --migrationPath=@yii/rbac/migrations

จะได้ตารางต่างๆ ในฐานข้อมูลโดยมีตารางต่างๆ ดังนี้
 
auth_item เป็นตารางเก็บ Permission หรือ สิทธิ์ ว่าในระบบมีเส้นทางอะไรบ้าง
auth_item_child เป็นตารางเก็บรายละเอียดแต่ล่ะสิทธ์ว่าสามารถเข้าถึงอะไรบ้าง
auth_assignment เป็นตารางเก็บการกำหนดสิทธิ์ให้แต่ละ User ID
auth_rule เป็นตารางเก็บกฎต่างๆ ที่เพิ่มขึ้นจาก Class เช่น การแก้ไขโพส ของตัวเอง

 

สร้าง RbacController

ในขั้นตอนนี้เป็นการสร้าง RbacController โดยสร้างใน console/controllers ซึ่งจะสืบทอดมาจาก Class yii\console\Controller 
 
ทดสอบโดยสร้าง Class RbacController และสร้าง actionHello() เพื่อทดสอบ console โดยมีรายละเอียดดังนี้

<?php
#RbacController.php
//yii rbac/hello
namespace console\controllers;

use yii\console\Controller;
use Yii;

class RbacController extends Controller
{
    public function actionHello()
    {
        echo 'Hello';
    }
}


จากนั้นเปิด CommandPrompt เพื่อทดสอบการทำงานโดยเข้าไปที่ Project จากนั้นพิมพ์คำสั่ง yii rbac/hello หากทำงานถูกต้องจะมีการแสดงผลดังนี้

Hello

การสร้างการอนุญาต (Permission)

สำหรับการอนุญาตในการเข้าถึงระบบนั้นจะใช้การสร้างเส้นทาง (Route) ในแต่ละ action เช่น module/controller/action โดยเพิ่ม actionCreatePermission() ในไฟล์ console/controllers/RbacController.php และกำหนดรายละเอียดดังนี้

public function actionCreatePermission()
    {
        //yii rbac/create-permission
        $auth = Yii::$app->authManager;
        
        // โพส (Post)
        $post_index = $auth->createPermission('post/index');
        $post_index->description = 'รายการโพส';
        $auth->add($post_index);
        
        $post_create = $auth->createPermission('post/create');
        $post_create->description = 'เพิ่มโพส';
        $auth->add($post_create);
        
        $post_update = $auth->createPermission('post/update');
        $post_update->description = 'แก้ไขโพส';
        $auth->add($post_update);
        
        $post_delete = $auth->createPermission('post/delete');
        $post_delete->description = 'ลบโพส';
        $auth->add($post_delete);
        
        $post_view = $auth->createPermission('post/view');
        $post_view->description = 'ดูโพส';
        $auth->add($post_view);
        echo 'Create Permission success!';
    }   


เรียกใช้งานผ่าน command prompt โดยเข้าไปที่ root ของ project แล้วเรียกคำสั่ง 
yii rbac/create-permission
หากทำถูกต้องจะปรากฏข้อความ
Create Permission success!
และจะเห็นข้อมูลในตาราง 
auth_item
    

การสร้างบทบาท (Role)

สำหรับบทบาท (Role) นั้นเป็นบทบาทที่มีการใช้ในระบบโดยเราสามารถกำหนดบทบาทได้หลายบทบาทตัวอย่างเช่น user เป็นบทบาทปกติหรือบทบาทเริ่มต้นใช้งานระบบได้เพียง action index และ view เท่านั้น บทบาท staff เป็นเจ้าหน้าที่โดยเจ้าหน้าที่เป็น user เช่นกัน แต่มีบทบาทเพิ่มขึ้นคือเข้า create ได้ และบทบาท admin 

บทบาท/action

index

view

create

update

delete

User

ใช่

ใช่

-

-

-

Staff

-

-

ใช่

-

-

Admin

-

-

-

ใช่

ใช่

เนื่องจาก staff จะกำหนดให้สามารถแก้ไขได้เฉพาะโพสตัวเอง จึงยังไม่ได้กำหนดการเข้าถึง update ได้ในขณะนี้ และบทบาทนั้นมีการเชื่อมโยงกันในลักษณะดังนี้
 
จะเห็นได้ว่า admin คือ staff ซึ่งสามารถเข้าถึงการอนุญาต (Permission) ของ staff ได้ และ
staff คือ user ซึ่งสามารถเข้าถึงการอนุญาต (Permission) ของ user ได้เช่นกัน
โดยเพิ่ม actionCreateRole() เพื่อกำหนดบทบาทของผู้ใช้งานดังนี้

public function actionCreateRole()
    {
        //yii rbac/create-role
        $auth = Yii::$app->authManager;
        
        // post
        $post_index = $auth->createPermission('post/index');
        $post_create = $auth->createPermission('post/create');
        $post_update = $auth->createPermission('post/update');
        $post_delete = $auth->createPermission('post/delete');
        $post_view = $auth->createPermission('post/view');
        
        $user = $auth->createRole('user');
        $auth->add($user);
        $auth->addChild($user, $post_index);
        $auth->addChild($user, $post_view);
        
        $staff = $auth->createRole('staff');
        $auth->add($staff);
        $auth->addChild($staff, $post_create);
        $auth->addChild($staff, $user);
        
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $post_update);
        $auth->addChild($admin, $post_delete);
        $auth->addChild($admin, $staff);
        echo 'Create Role success!';
    }


เรียกใช้งานผ่าน command prompt โดยเข้าไปที่ root ของ project แล้วเรียกคำสั่ง 
yii rbac/create-role
หากทำถูกต้องจะปรากฏข้อความ
Create Role success!
และจะเห็นข้อมูลในตาราง 
auth_item_child

การกำหนดสิทธิ์ (Assignment)

การกำหนดสิทธิ์ให้กับผู้ใช้งานแต่ละคนว่าให้มีบทบาทอะไรบ้าง โดยเพิ่ม actionCreateAssignment() และเขียนโปรแกรมในการกำหนดสิทธิ์ดังนี้

public function actionCreateAssignment()
    {
        $auth = Yii::$app->authManager;
        $user = $auth->createRole('user');
        $staff = $auth->createRole('staff');
        $admin = $auth->createRole('admin');
        
        $auth->assign($user, 3);
        $auth->assign($staff, 2);
        $auth->assign($admin, 1);
        echo 'Create Assignment success!';
    }


เรียกใช้งานผ่าน command prompt โดยเข้าไปที่ root ของ project แล้วเรียกคำสั่ง 
yii rbac/create-assignment
หากทำถูกต้องจะปรากฏข้อความ
Create Assignment success!
และจะเห็นข้อมูลในตาราง 
auth_assignment

การสร้างกฎเพิ่มเติม (Rule)

กฎ (Rule) เป็น Class ที่สร้างขึ้นเพื่อการกำหนดความต้องการเพิ่มเติมสำหรับการเข้าถึง action ต่างๆ เช่นการแก้ไขได้เฉพาะโพสของตัวเอง เป็นต้น โดยการสร้าง Class StaffRule เก็บไว้ที่ common\components\StaffRule.php โดยกฎนี้เป็นการตรวจสอบ $model ว่า attribute ของเจ้าของโพสเป็น User ที่อยู่ในระบบหรือเปล่าโดยกำหนด attribute เป็น user_id นั่นเอง หากต้องการใช้ attribute ชื่ออื่นก็ให้เปลี่ยน user_id เป็นชื่ออื่นได้ตามต้องการ

<?php
namespace common\components;

use yii\rbac\Rule;
use Yii;

class StaffRule extends Rule{
    public $name = 'isStaff';
    
    public function execute($user, $item, $params) { //abstract method implement
        //return isset($params['post']) ? $params['post']->user_id == $user : false;
        if(isset($params['model'])){
            $model = $params['model'];
        }else{
            $id = Yii::$app->request->get('id');
            $model = Yii::$app->controller->findModel($id);
        }
        return $model->user_id == $user;
    }

}


จากนั้นเพิ่ม actionCreateRule() ในไฟล์ console\controllers\RbacController.php ดังนี้

public function actionCreateRule()
    {
        //เรียกใช้งาน yii rbac/create-rule
        $auth = Yii::$app->authManager;

        // add the rule
        $rule = new \common\components\StaffRule;
        $auth->add($rule);

        
        
        // add the "updateOwnPost" permission and associate the rule with it.
        $updateOwnPost = $auth->createPermission('updateOwnPost');
        $updateOwnPost->description = 'ปรับปรุงข้อมูลการโพสของตัวเอง';
        $updateOwnPost->ruleName = $rule->name;
        $auth->add($updateOwnPost);
        
        $post_update = $auth->createPermission('post/update');
        

        // "updateOwnPost" will be used from "updatePost"
        $auth->addChild($updateOwnPost, $post_update);
        
        // allow "staff" to update their own posts
        $staff = $auth->createPermission('staff');
        $auth->addChild($staff, $updateOwnPost);
        echo 'Generate UpdateOwnPost Success!';
    }


เรียกใช้งานผ่าน command prompt โดยเข้าไปที่ root ของ project แล้วเรียกคำสั่ง 
yii rbac/create-rule
หากทำถูกต้องจะปรากฏข้อความ
Create UpdateOwnPost success!
และจะเห็นข้อมูลในตาราง 
auth_item_child
auth_rule

เพิ่ม Access Control Filter (ACF) ใน Controller

Access Control Filter (ACF) เป็นการเพิ่มการตรวจสอบโดยใช้ Filter ของ Controller ในที่นี้จะทำการปรับแต่งในส่วน PostController โดยเพิ่มใน Method behaviors() ในส่วนของ ‘access’  ดังนี้

public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                        'matchCallback' => function ($rule, $action) {
                            $module     = Yii::$app->controller->module->id;
                            $action     = Yii::$app->controller->action->id;
                            $controller = Yii::$app->controller->id;
                            $route      = "$module/$controller/$action";
                            if(Yii::$app->user->can($route)){
                                return true;
                            }
                        }
                    ]
                ]
            ]
        ];
    }

ทดสอบการใช้งาน RBAC

ทดสอบการใช้งานโดยเข้าระบบในแต่ละสิทธิ์โดยเริ่มจาก user แล้วทดลองเข้า action index และ view ว่าสามารถเข้าถึงได้หรือไม่ จากนั้นทดสอบโดยการเข้า action create จะต้องปรากฏหน้าแจ้ง Error ดังนี้

Forbidden (#403)
คุณไม่ได้รับอนุญาตให้ดำเนินการนี้
 
และลองทดสอบเช่นเดียวกันกับผู้ใช้งานที่มีสิทธิ์เป็น staff และ admin โดย staff จะต้องไม่สามารถแก้ไข (update) โพสของคนอื่นได้นอกจากโพสของตัวเอง และไม่สามารถลบ (delete) ได้ และ admin สามารถใช้งานได้ทุกๆ action

 


หากบทเรียนรู้มีความผิดพลาดประการใด หรือมีข้อเสนอแนะกรุณาแจ้ง contact@programmerthailand.com
มานพ กองอุ่น

มานพ กองอุ่น
admin

  • 2 เพื่อน
  • 13 ผู้ติดตาม
  • 763 โพสต์