Yii2 - Додавання RBAC на сайт, контроль доступу на основі ролей

  • Останнє оновлення: 3 Квітня 2024 р.
  • Перегляди: 26
  • Автор: Адмін
Yii2 - Додавання RBAC на сайт, контроль доступу на основі ролей

Колеги всім привіт.

У сьогоднішній статті ми поговоримо про те, як налаштувати RBAC в yii2. Якщо хтось не знає, то RBAC це один з компонентів у yii2 який відповідає за контроль доступу на основі ролей. Наприклад, у вас є якась дія і потрібно перевірити, чи має право поточний користувач виконувати ці дії чи ні. Глибина успадкування в RBAC практично не має меж, можна створювати скільки завгодно ролей і потім надавати їх користувачам.

За замовчуванням RBAC в yii2 вимкнено. І так давайте його налаштуємо.

 

Перше що вам потрібно знати про RBAC це те, що його правила можуть зберігатися як у звичайному файлі, так і в базі даних.

  • yii\rbac\PhpManager - Зберігання правил у файлах.
  • yii\rbac\DbManager - Зберігання правил у базі даних.

У цій статті я показуватиму роботу yii \ rbac \ DbManager, так як на мою він більш практичний ніж yii \ rbac \ PhpManager.

 

Перший крок по налаштуванню RBAC це його включити в конфігураційному файлі web.php і console.php.

'authManager' => [
    'class' => 'yii\rbac\DbManager',
    'cache' => 'cache'
]

yii2_rbac

Крім самого RBAC, ми ще включаємо кешування властивістю 'cache' => 'cache' щоб знизити навантаження на базу даних.


 

Наступною дією нам необхідно підготувати базу даних для rbac. rbac у своїй роботі використовуватиме 4 таблиці, і нам потрібно буде їх створити.

  • auth_item: таблиця містить role/permitssion та їх опис.
  • auth_item_child: зберігає спадкування role/permitssion один від одного.
  • auth_assignment: Тут дані призначення користувачам role/permission.
  • auth_rule: зберігання індивідуальних правил.

yii2_rbac


 

Ми можемо створити ці таблиці двома способами.

Перший спосіб це виконати команду міграції в консолі, яка створить таблиці автоматично:

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

yii2_rbac

 

Другий спосіб це створити ці таблиці вручну:

CREATE TABLE `auth_assignment` (
  `item_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `user_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`item_name`,`user_id`),
  KEY `idx-auth_assignment-user_id` (`user_id`),
  CONSTRAINT `auth_assignment_ibfk_1` FOREIGN KEY (`item_name`) 
  REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

CREATE TABLE `auth_item` (
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `type` smallint(6) NOT NULL,
  `description` text COLLATE utf8_unicode_ci DEFAULT NULL,
  `rule_name` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `data` blob DEFAULT NULL,
  `created_at` int(11) DEFAULT NULL,
  `updated_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`name`),
  KEY `rule_name` (`rule_name`),
  KEY `idx-auth_item-type` (`type`),
  CONSTRAINT `auth_item_ibfk_1` FOREIGN KEY (`rule_name`) 
  REFERENCES `auth_rule` (`name`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

CREATE TABLE `auth_item_child` (
  `parent` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `child` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`parent`,`child`),
  KEY `child` (`child`),
  CONSTRAINT `auth_item_child_ibfk_1` FOREIGN KEY (`parent`) 
  REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `auth_item_child_ibfk_2` FOREIGN KEY (`child`) 
  REFERENCES `auth_item` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

CREATE TABLE `auth_rule` (
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `data` blob DEFAULT NULL,
  `created_at` int(11) DEFAULT NULL,
  `updated_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

Тепер коли ми включили rbac і створили таблиці, то тепер давайте створимо кілька ролей.

Перша роль у нас називатиметься Admin.

$role = Yii::$app->authManager->createRole('admin');
$role->description = 'Admin';
Yii::$app->authManager->add($role);

Другу роль ми назвемо Manager.

$role = Yii::$app->authManager->createRole('author');
$role->description = 'Manager';
Yii::$app->authManager->add($role);

 

Тепер коли ми створили пару ролей на нашому сайті, то тепер ми можемо їх використовувати у фільтрі AccessControl, для налаштування доступу.

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['adminpanel'],
                    'allow' => true,
                    'roles' => ['admin'],
                ],
            ],
        ]
    ];
}

Цим кодом ми вказуємо, що доступ до дії adminpanel можна отримати тільки тим користувачам, які мають роль admin. Але користувача з такою роллю у нас поки що немає, а є тільки роль.


 

Ще одна особливість rbac у тому, що ми можемо створювати не лише ролі, а й права. Права створюються так само як і ролі.

$permit = Yii::$app->authManager->createPermission('grantModerator');
$permit->description = 'Grant moderator';
Yii::$app->authManager->add($permit);

Yii2 сам не перевірятиме права користувача. Ім'я "grantModerator" - просто звичайний рядок, він ніяк не співвідноситься з action та іншими сутностями в Yii2. Перевірити, чи має право користувач на дії, ви повинні самі.

if(Yii::$app->user->can('grantModerator'))
{
    //perform some action
}
else throw new ForbiddenHttpException('You do not have sufficient rights to perform the specified action');

 

У Yii2 ролі та права можна успадковувати, причому без обмежень, що від чого успадковується.

Наслідувати можна:

  • роль від ролі
  • роль від права
  • право від ролі
  • право від права

 

Тепер настав час прив'язати нашу роль якомусь користувачеві, в моєму випадку я прив'язуватиму роль admin до користувача administrator. Прив'язка здійснюється за ID користувача в базі даних і робиться один раз. rbac збереже дані в таблицю auth_assignment і підхоплюватиме роль автоматично при авторизації користувача. Прив'язку краще робити при створенні нового користувача.

$userRole = Yii::$app->authManager->getRole('admin');
Yii::$app->authManager->assign($userRole, Yii::$app->user->getId());

Прив'язувати до користувача можна як ролі, а й права.

$permit = Yii::$app->authManager->getPermission('grantModerator');
Yii::$app->authManager->assign($permit, Yii::$app->user->getId());

Прив'язка права здійснюється так само за ID користувача в базі даних і робиться один раз.

 

Користувач може мати кілька ролей. Щоб отримати всі ролі користувача можна зробити так:

Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());

 

Дякую всім, я сподіваюся що вам моя стаття хоч чимось допомогла.

СХОЖІ СТАТТІ

Yii2 - як відключити CSRF валідацію токена
Як отримати розширення файлу - PHP