Giới thiệu về zend-permissions-rbac

zend-permissions-rbac là một công cụ nhẹ triển khai phân quyền RBAC (role - based access control)  dựa vào các lớp chuẩn PHP là RecursiveIterator và  RecursiveIteratorIterator.RBAC khác với ACL tập trung vào các role hơn là các resourece.  Các khái niệm cần biết ở đây gồm:

  • Một identity (định danh) có một hoặc nhiều Role.
  • Một role yêu cầu quyền truy cập.
  • Một permission được chuyển cho Role.

 Mối quan hệ giữa identity và role, giữa role và permision là mối quan hệ Nhiều - Nhiều. 

Để cài đặt zend-permisions-rbac dùng composer như sau:

composer require zendframework/zend-permissions-rbac

Lưu ý đọc phân quyền với ACL với Zend trước. Các mục sau đây cách tạo và sử dụng khá tương tự ACL.

Tạo Role

Sử dụng Zend\Permission\Rbac\Role và sau đó đưa vào bộ chứa RBAC bằng lệnh addRole(). Các Role có tính kế thừa, nếu Role con có quyền mặc định Role cha sẽ có quyền.

Tạo Permission

Mỗi Role có thể có các Permission và có thể thiết lập trực tiếp role bằng cách lấy từ trình chứa RBAC và có sự kế thừa cha chon giữa các role. 

Ví dụ: 

<?php
use Zend\Permissions\Rbac\Rbac;
use Zend\Permissions\Rbac\Role;


include "vendor/autoload.php";

//Tạo trình chứa Rbac
$rbac = new Rbac();

//Tạo một role
$member  = new Role('manager');

//Thêm đối tượng Role vào rabc
$rbac->addRole($member);

$rbac->addRole('admin', 'manager' );

$rbac->addRole('moderator', 'admin');

$rbac->addRole('editor', 'admin');

$rbac->addRole('member', ['moderator', 'editor']);

/**
 * Các quyền view.post
 */

$rbac->getRole('member')->addPermission("view.post");
$rbac->getRole('editor')->addPermission('edit.post');
$rbac->getRole('moderator')->addPermission('createforum');
$rbac->getRole('admin')->addPermission('ban.user');
$rbac->getRole('manager')->addPermission('turnoffwebsite');

function check($role, $permission) {
    global $rbac;
    echo "\t$permission:\t".($rbac->isGranted($role, $permission)?'ĐƯỢC PHÉP':'*'), PHP_EOL;

}

$roles = ['manager', 'admin', 'moderator', 'editor', 'member'];
$permissions = ['view.post', 'edit.post', 'createforum', 'ban.user', 'turnoffwebsite'];
echo "<pre>";
foreach ($roles as $role) {
    echo $role, PHP_EOL;
    foreach ($permissions as $permission)
        check($role, $permission);

}
echo "</pre>";

Chạy mã trên ra kết quả:

manager
	view.post:	ĐƯỢC PHÉP
	edit.post:	ĐƯỢC PHÉP
	createforum:	ĐƯỢC PHÉP
	ban.user:	ĐƯỢC PHÉP
	turnoffwebsite:	ĐƯỢC PHÉP
admin
	view.post:	ĐƯỢC PHÉP
	edit.post:	ĐƯỢC PHÉP
	createforum:	ĐƯỢC PHÉP
	ban.user:	ĐƯỢC PHÉP
	turnoffwebsite:	*
moderator
	view.post:	ĐƯỢC PHÉP
	edit.post:	*
	createforum:	ĐƯỢC PHÉP
	ban.user:	*
	turnoffwebsite:	*
editor
	view.post:	ĐƯỢC PHÉP
	edit.post:	ĐƯỢC PHÉP
	createforum:	*
	ban.user:	*
	turnoffwebsite:	*
member
	view.post:	ĐƯỢC PHÉP
	edit.post:	*
	createforum:	*
	ban.user:	*
	turnoffwebsite:	*

Tương tự như Acl, bạn cũng có thể dùng Assert để kiểm tra quyền cập nhật theo thời gian chạy, ví dụ:

use Zend\Permissions\Rbac\AssertionInterface;
use Zend\Permissions\Rbac\Rbac;

class AssertUserIdMatches implements AssertionInterface
{
    protected $userId;
    protected $article;

    public function __construct($userId)
    {
        $this->userId = $userId;
    }

    public function setArticle($article)
    {
        $this->article = $article;
    }

    public function assert(Rbac $rbac)
    {
        if (! $this->article) {
            return false;
        }

        return ($this->userId === $this->article->getUserId());
    }
}

// User is assigned the foo role with id 5
// News article belongs to userId 5
// Jazz article belongs to userId 6

$rbac = new Rbac();
$user = $mySessionObject->getUser();
$news = $articleService->getArticle(5);
$jazz = $articleService->getArticle(6);

$rbac->addRole($user->getRole());
$rbac->getRole($user->getRole())->addPermission('edit.article');

$assertion = new AssertUserIdMatches($user->getId());
$assertion->setArticle($news);

// true always - bad!
if ($rbac->isGranted($user->getRole(), 'edit.article')) {
    // hacks another user's article
}

// true for user id 5, because he belongs to write group and user id matches
if ($rbac->isGranted($user->getRole(), 'edit.article', $assertion)) {
    // edits his own article
}

$assertion->setArticle($jazz);

// false for user id 5
if ($rbac->isGranted($user->getRole(), 'edit.article', $assertion)) {
    // can not edit another user's article
}

Đăng ký nhận bài viết mới