Эта статья является дополнением и продолжением предыдущей статьи по авторизации в Yii2. В ней мы рассмотрим контроль доступа к модулям, контроллерам, действиям и отдельным функциям на основе встроенного в Yii2 механизма RBAC.
Для начала нужно сказать о самом главном аспекте RBAC — его области применения, в подавляющем большинстве случаев полноценный контроль доступа на основе ролей нужен для систем, в которых администратору придется динамически изменять права у различных групп пользователей через панель администратора или любой другой интерфейс.
Вторым важным аспектом является понимание терминов с которыми работает RBAC:
- роль (role) — принадлежность пользователя к какой-либо группе, которая определяет его права доступа. Примеры: администратор, модератор, обычный пользователь.
- разрешение (permission) — возможность доступа к какому-либо функционалу. Примеры: открытие страницы, добавление статьи, редактирование личных данных.
- правило (rule) — набор требований к пользователю, которым он должен соответствовать для получения доступа к функционалу. Правила могут крепиться как к роли(role), так и к разрешению(permission). Примеры: проверка авторства статьи перед её редактированием, проверка подтверждения контактных данных покупателя в магазине перед оформлением покупки, проверка возраста пользователя перед заказом билета.
- привязка (assigment) — установка связей между сущностями RBAC. Примеры: привязка роли к пользователю, привязка правила к пользователю.
- наследование (в Yii2 — addChild()) — передача прав доступа (разрешений и правил). Примеры: наследование роли от роли, роли от разрешения.
Давайте перейдем к обзору реализации RBAC в Yii2, точнее к двум её вариантам: PhpManager и DbManager. Различие между этими двумя реализациями состоит в способе хранения данных, в PHP файлах и базе данных соответственно. К плюсам PhpManager’а можно отнести скорость работы на небольшом количестве пользователей из-за хранения всей инфраструктуры менеджера в файлах, но этот плюс постепенно превращается в минус при росте количества пользователей, так как эти файлы начинают расти в размерах. Сильной стороной DbManager’а является гибкое управление политикой доступа (для этих задач обычно реализуется раздел в панели администратора) к функционалу и относительно высокая скорость работы при большом количестве пользователей.
В примерах этой статьи используется шаблон приложения basic.
Для подключения RBAC менеджера нужно настроить компонент в двух файлах конфигурации: «../config/web.php» и «../config/console.php».
return [
// Другие параметры.
'components' => [
'authManager' => ['class' => 'yii\rbac\DbManager'], // или 'yii\rbac\PhpManager'.
// Другие параметры.
],
];
Для функционирования DbManager’а требуется настроенное подключение к БД и применение миграции от разработчиков фреймворка:
yii migrate --migrationPath=@yii/rbac/migrations
А для работы PhpManager’а необходимо лишь наличие директории @app/rbac/ с правами записи для сервера.
После подключения RBAC-менеджера необходимо создать требуемые роли, разрешения и правила, которые можно будет присоединять к пользователю. Для небольших систем эти операции выводят в отдельный контроллер (RbacController например) или в миграцию, но вы можете делать это там, где заходите, разницы никакой нет. А для больших систем часто пишут свою надстройку для управления правами доступа или используют стороннее расширение наподобие yii2-admin.
РОЛИ
Для примера создадим три роли: администратор, модератор и пользователь.
$roleAdministrator = Yii::$app->authManager->createRole('administrator');
$roleAdministrator->description = 'Администратор';
Yii::$app->authManager->add($roleAdministrator);
$roleModerator = Yii::$app->authManager->createRole('moderator');
$roleModerator->description = 'Модератор';
Yii::$app->authManager->add($roleModerator);
$roleUser = Yii::$app->authManager->createRole('user');
$roleUser->description = 'Пользователь';
Yii::$app->authManager->add($roleUser);
После выполнения кода выше в таблице auth_item (для DbManager) или в файле app/rbac/items (для PhpManager) должны появиться записи для наших ролей. Эти роли уже можно использовать для контроля доступа. Чтобы протестировать работу нашего менеджера привяжем каждую из ролей к разным пользователям.
// Достаем пользователя Иванова из БД.
$ivanov = User::findOne(1);
// Достаем роль администратора из RBAC-менеджера.
$roleAdministrator = Yii::$app->authManager->getRole('administrator');
// Привязываем роль администратора к идентификатору Иванова.
Yii::$app->authManager->assign($roleAdministrator, $ivanov->getId());
// Достаем пользователя Петрова из БД.
$petrov = User::findOne(2);
// Достаем роль модератора из RBAC-менеджера.
$roleModerator = Yii::$app->authManager->getRole('moderator');
// Привязываем роль модератора к идентификатору Петрова.
Yii::$app->authManager->assign($roleModerator, $petrov->getId());
// Достаем пользователя Сидорова из БД.
$sidorov = User::findOne(3);
// Достаем роль модератора из RBAC-менеджера.
$roleUser = Yii::$app->authManager->getRole('user');
// Привязываем роль пользователя к идентификатору Сидорова.
Yii::$app->authManager->assign($roleUser, $sidorov->getId());
В реальных приложениях пользователям присваивают роли при регистрации в системе, здесь же для примера они были добавлены ранее и найдены через findOne() по идентификатору. После выполнения этого кода в таблице auth_assignment (для DbManager) или в файле app/rbac/items (для PhpManager) добавятся записи для связи ролей и пользователей.
Если вы раньше не использовали RBAC менеджер, то скорее всего создавали поле «role» в таблице пользователей и записывали туда присвоенное имя роли. Теперь вся работа с ролями будет происходить через RBAC менеджер и в поле «role» нет надобности.
Давайте создадим две условные страницы для управления статьями и пользователями к которым ограничим доступ некоторым пользователям. К странице управления статьями будет доступ только у администратора, а к управлению статьями будет доступ у администратора и у модератора. Пользователь же останется вообще без доступа.
[
'class' => AccessControl::class,
'only' => ['manage-users', 'manage-articles'],
'denyCallback' => function () {
die('Доступ запрещен!');
},
'rules' => [
[
'allow' => true,
'actions' => ['manage-users'],
'roles' => ['administrator'],
],
[
'allow' => true,
'actions' => ['manage-articles'],
'roles' => ['administrator', 'moderator'],
],
],
],
];
}
public function actionManageUsers()
{
echo 'Управление пользователями доступно только администратору.';
}
public function actionManageArticles()
{
echo 'Управление статьями доступно администратору и модератору.';
}
}
Если вам ранее приходилось использовать фильтры контроля доступа (ACF), то представленный выше способ ограничения доступа покажется знакомым за одним исключением — появилась возможность указывать свои роли в параметре «roles» вместо двух стандартных @ и ?.
РАЗРЕШЕНИЯ
Разрешения позволят нам более гибко управлять доступом. Продолжим развивать предыдущий пример: создадим разрешение на доступ к странице управления пользователями (SiteController/ManageArticles) и добавим его к роли модератора, что бы Петров тоже мог видеть всех пользователей:
// Создаем разрешение на доступ к странице управления пользователями.
$permissionManageUsers = Yii::$app->authManager->createPermission('view_manage_users_page');
// Добавляем своё описание к разрешению, чтобы не забыть для чего мы его создавали.
$permissionManageUsers->description = 'Доступ к странице управления пользователями.';
// Добавляем разрешение в систему через RBAC менеджер.
Yii::$app->authManager->add($permissionManageUsers);
// Ищем роль модератора.
$roleModerator = Yii::$app->authManager->getRole('moderator');
// Добавляем (наследуем) разрешение для роли модератора.
Yii::$app->authManager->addChild($roleModerator, $permissionManageUsers);
После создания и привязки разрешения мы можем начать с ней работать. Есть два варианта: через ACF и через метод «can()» в компоненте «User».
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['manage-users'],
'denyCallback' => function () {
die('Доступ запрещен!');
},
'rules' => [
[
'allow' => true,
'actions' => ['manage-users'],
'roles' => ['view_manage_users_page'], // Разрешения как и роли можно использовать тут.
],
],
],
];
}
public function actionManageUsers()
{
echo 'Управление пользователями доступно только администратору.';
}
Через метод «can()» в компоненте «User»:
public function actionManageUsers()
{
if (Yii::$app->user->can('view_manage_users_page')) {
echo 'Доступ есть.';
} else {
echo 'Доступ закрыт.';
}
echo 'Управление пользователями доступно только администратору.';
}
С помощью разрешений вы без труда сможете контролировать доступ не только к целым модулям, контроллерам или действиям, но и к частям представлений.
ПРАВИЛА
Правила в RBAC являются «вишенкой на торте» в управлении доступом, так как они позволяют еще точнее задать условия доступа для каждой роли и даже для отдельного пользователя. Еще больше разовьем наш пример и задействуем последнего пользователя — Сидорова, который пока не принимал участия в работе на системой. Дадим возможность редактировать свои статьи всем пользователям.
Для начала создадим само правило проверки авторства статьи:
user_id == $user;
}
}
Теперь добавим это правило в систему и прикрепим к роли пользователя:
// Достаем пользователя Сидорова из БД.
$sidorov = User::findOne(3);
// Достаем роль модератора из RBAC-менеджера.
$roleUser = Yii::$app->authManager->getRole('user');
// Привязываем роль пользователя к идентификатору Сидорова.
Yii::$app->uthManager->assign($roleUser, $sidorov->getId());
// Создаем объект класса нашего правила (листинг этого класса ниже).
$ruleCheckOwner = new OwnerRule();
// Добавляем правило в систему.
Yii::$app->authManager->add($ruleCheckOwner);
// Создаем разрешение "update_own_article" для владельцев статей.
$updateOwnArticle = Yii::$app->authManager->createPermission('update_own_article');
// Добавляем своё описание, чтобы не забыть зачем мы создавали это правило.
$updateOwnArticle->description = 'Правило для проверки авторства статьи.';
// Добавляем наименование используемого правила в наше разрешение.
$updateOwnArticle->ruleName = $ruleCheckOwner->name;
// Добавляем разрешение в систему.
Yii::$app->authManager->add($updateOwnArticle);
// Прикрепляем к роли пользователя право редактировать свои статьи.
$auth->addChild($roleUser, $updateOwnArticle);
Осталось опробовать наше правило:
user->can('update_own_article', ['article' => $article])) {
echo 'Этот пользователь может редактировать статью.';
} else {
echo 'Статья не принадлежит пользователю.';
}
}
}
На этом описание работы встроенного в Yii2 RBAC менеджера закончено. Если вам показалось, что в управлении доступом на основе ролей трудно разобраться, то это только первое впечатление, оно когда-то было и у меня. После пары часов практики все должно проясниться, главное начать пробовать.
Комментарии (0)