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

  • Последнее обновление: 3 Апреля 2024 г.
  • Просмотры: 27
  • Автор: Админ
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/permitssion.
  • 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
Как сгенерировать случайное и уникальное число в PHP
PHP - Как узнать кодировку сайта.