Yii2 и RBAC. Настройка и использование ролей

Просмотров: 29313Комментарии: 14
Yii2 Framework
Yii2 и RBAC. Настройка и использование ролей

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


RBAC (Role Based Access Control)- управление доступом на основе ролей. Разграничение доступа на основе ролей позволяет реализовать гибкие и динамические правила доступа для функционирования веб-приложения.

В данном примере я рассмотрю использование RBAC на основе приложения yiisoft/yii2-app-advanced. Разницы конечно же нету какое у Вас приложение, но структура можем отличаться.

Структура папок advanced шаблона простым языком можно описать так:

backend //приложение админки
common //общая конфигурация и компоненты
console //приложение для использования консоли
environments //используется лишь для копирования конфигурационных файлов
             //при инициализации шаблона командой init (dev|prod)
frontend //основное приложение
vendor //сам фреймворк и другие библиотеки

Настройка RBAC

Функциональность RBAC обеспечивает компонент приложения AuthManager. Поэтому в первую очередь настраиваем его. Рассмотрим пример использования стандартного класса PhpManager. При использовании DbManager прописываем только класс и роли.

Допустим, что наши настройки ролей будут храниться в папке common\components\rbac\.

Изменяем файл конфигурации \common\config\main.php

'components' => [
    'authManager' => [
        'class' => 'yii\rbac\PhpManager',
        'defaultRoles' => ['user','moder','admin'], //здесь прописываем роли
        //зададим куда будут сохраняться наши файлы конфигураций RBAC
        'itemFile' => '@common/components/rbac/items.php',
        'assignmentFile' => '@common/components/rbac/assignments.php',
        'ruleFile' => '@common/components/rbac/rules.php'
    ],
    ...
],

Создадим обработчик для правил доступа

Для начало дополним нашу модель \common\models\User.php новыми константами для трех ролей, так как они у нас используются в обработчике для наглядности.

const ROLE_USER = 1;
const ROLE_MODER = 5;
const ROLE_ADMIN = 10;

Создадим файл обработки правил доступа в папке common\components\rbac\UserRoleRule.php.

Файл будет иметь следующий код, который будет разруливать правила.

<?php
namespace common\components\rbac;
use Yii;
use yii\rbac\Rule;
use yii\helpers\ArrayHelper;
use common\models\User;
class UserRoleRule extends Rule
{
    public $name = 'userRole';
    public function execute($user, $item, $params)
    {
        //Получаем массив пользователя из базы
        $user = ArrayHelper::getValue($params, 'user', User::findOne($user));
        if ($user) {
            $role = $user->role; //Значение из поля role базы данных
            if ($item->name === 'admin') {
                return $role == User::ROLE_ADMIN;
            } elseif ($item->name === 'moder') {
                //moder является потомком admin, который получает его права
                return $role == User::ROLE_ADMIN || $role == User::ROLE_MODER;
            } 
            elseif ($item->name === 'user') {
                return $role == User::ROLE_ADMIN || $role == User::ROLE_MODER
                || $role == User::ROLE_USER;
            }
        }
        return false;
    }
}

Создание данных авторизации

Для создания данных мы используем консольное приложение. Для этого создадим контроллер console\controllers\RbacController.php, который будет генерировать конфигурацию RBAC при его запуске.

<?php
namespace console\controllers;
use Yii;
use yii\console\Controller;
use common\components\rbac\UserRoleRule;
class RbacController extends Controller
{
    public function actionInit()
    {
        $auth = Yii::$app->authManager;
        $auth->removeAll(); //удаляем старые данные
        //Создадим для примера права для доступа к админке
        $dashboard = $auth->createPermission('dashboard');
        $dashboard->description = 'Админ панель';
        $auth->add($dashboard);
        //Включаем наш обработчик
        $rule = new UserRoleRule();
        $auth->add($rule);
        //Добавляем роли
        $user = $auth->createRole('user');
        $user->description = 'Пользователь';
        $user->ruleName = $rule->name;
        $auth->add($user);
        $moder = $auth->createRole('moder');
        $moder->description = 'Модератор';
        $moder->ruleName = $rule->name;
        $auth->add($moder);
        //Добавляем потомков
        $auth->addChild($moder, $user);
        $auth->addChild($moder, $dashboard);
        $admin = $auth->createRole('admin');
        $admin->description = 'Администратор';
        $admin->ruleName = $rule->name;
        $auth->add($admin);
        $auth->addChild($admin, $moder);
    }
}

Теперь открываем консоль, переходим в основную папку yii нашего проекта. И выполняем команду, которая вызовет наш созданный контроллер Rbac и экшен Init.

php yii rbac/init

В папке \common\components\rbac\ у нас появится три файла конфигурации assignments.php, items.php и rules.php.

Если нам понадобится изменить некоторые права, просто редактируем данный контроллер и вызываем снова команду в консоли.

Использование в контроллере

Для того, чтобы ограничить доступ к какому либо экшену нашего контроллера, мы можем прописывать наши роли в функции behaviors().

Пример:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'allow' => true,
                    'actions'=>['login','error'],
                    'roles' => ['?'],
                ],
                [
                    'allow' => true,
                    'roles' => ['moder'],
                ],
            ],
        ],
        ...
    ];
}

В результате гости получат доступ только к экшенам login и error. А модератор и админ получают доступ везде.

Использование в коде

Теперь мы можем использовать наши роли в коде своего веб-приложения, к примеру так:

if(\Yii::$app->user->can('createUser')){
     //представление с формой для создания пользователей
}else{
     //представление показывающее пользователю ошибку
}

В нашем веб приложении можно использовать это, например, для доступа к админ-панели. Создадим модель User для приложения backend, копируем файл /common/models/LoginForm.php в папку /backend/models/. Открываем его и дописываем в use путь к модели User, иначе он ее потеряет и будет ругаться, также меняем namespace на новый:

namespace backend\models;
use common\models\User;

А функцию getUser() меняем к следующему виду:

public function getUser()
{
    if ($this->_user === false) {
        //Находим пользователя в БД по логину или эл.почте
        $this->_user = User::find()
            ->andWhere(['or', ['username' => $this->username],
                              ['email' => $this->username]])
            ->one();
        //Проверяем права доступа, если нет, то делаем вид,
        //что пользователь не найден.
        if (!Yii::$app->user->can('dashboard', ['user' => $this->_user])) {
            $this->_user = null;
        }
    }
    return $this->_user;
}

Также не забываем, что в контроллере админ-панели необходимо заменить путь к модели LoginForm, иначе никаких изменений не увидите.

use backend\models\LoginForm;

Если Вам захочется добавить еще одну роль, необходимо будет добавить ее в файл RbacController.php, в обработчик UserRoleRule.php и в файл конфигурации main.php в секцию defaultRoles

Комментариев: 14 RSS

1 roman 10-09-2014 19:15

После php yii rbac/init появляется сообщение Class yii\rbac\PhpManager does not exist

2 Admin 05-10-2014 03:00

Прекрасно работает на последней версии, проверил на новом приложении.

4 vladimir 09-10-2014 13:29

Вот только, что бы использовать if(\Yii::$app->user->can('createUser')) необходимо сперва создать Permission.

5 Влад 14-11-2014 19:11

Мануал довольно таки хороший, однако такое ощущение, что код писался на скорую руку. Имеются ошибки и не состыковки, что затрудняет понимание работы RBAC. Исправьте, если можно, пожалуйста.

6 Дмитрий 20-11-2014 08:09

Было бы круто, если бы описали, как настраивать yii\rbac\DbManager.

И визуализацию для него (контроллеры, модели, вьюшки).

PhpManager - это конечно хорошо, но ручками каждый раз править, чтобы добавить что то - это гемор.

7 Саня 18-12-2014 14:15

после выполнение команды "php yii rbac/init" указанные файлы не появляются. в чем может быть причина?

8 Станислав 21-12-2014 18:57

хорошая статья. заработало сходу, однако автору стоит писать более подробно.

молодец, автор!

9 Николай 14-01-2015 11:04

Статья отличная, но мне до конца картины не хватило следующего:

если залогиниться во фронтенде, админка полностью доступна

10 Иван 25-01-2015 01:04

Зачем в UserRoleRule использовать User::findOne($user); (лишний запрос к базе)?

Может заменить на \Yii::$app->user->identity ?

11 elmys 05-07-2015 15:32

наконец-то внятный мануал по RBAC Yii2. Спасибо!

13 Обезьяна 04-04-2016 12:53

Чувак, все правильно написал. Отличный Гайд. Только одна пометка. У меня файлы не создались после выполнения команды: php yii rbac/init Нужно самостоятельно создать файлы: iassignments.php, items.php и rules.php. А также в них прописать return [];

Использую xampp В целом все оч круто и понятно. Спасибо

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

     

  

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д., а также подписку на новые комментарии.

(обязательно)