RBAC, роли и пользователи в Yii2

Декабрь 24th, 2014
Метки:

Вопросы про RBAC, роли, авторизацию и связку ролей — одни из самых часто задаваемых на русскоязычном форуме Yii. Попробую ка я объяснить суть RBAC в Yii2.
RBAC бывает 2-типов: основанный на файлах или в БД. Я буду описывать тот, что хранит свои данные в БД, тк он дает больше возможностей динамически добавлять и менять роли.

Настройка authManager

В конфиге нужно прописать тип authManager-а

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

а в базе создать необходимые таблицы. Создавать их просто, достаточно применить миграцию:

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

Про миграции в Yii я уже писала.

Настройка ролей и прав

Теперь нужно создать роль и сохранить ее в RBAC

 $role = Yii::$app->authManager->createRole('admin');
 $role->description = 'Админ';
 Yii::$app->authManager->add($role);

 $role = Yii::$app->authManager->createRole('user');
 $role->description = 'Юзер';
 Yii::$app->authManager->add($role);

Делать это нужно всего 1 раз. Повторно сохранить роль с одним и тем же именем RBAC не даст. Теперь у нас есть роль админ и юзер. На что они имеют право? Пока ни на что, но можно указать права с привязкой к роли в контроллере

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

Теперь доступ к actionAdminka доступен только пользователю с ролью admin. Но пользователя с такой ролью у нас пока нет. Пока есть только роль.
Что еще важно: создавать можно не только роли, но и отдельные «права». Создаются они так же как и роли:

$permit = Yii::$app->authManager->createPermission('deleteUser');
$permit->description = 'Право удалять пользователя';
Yii::$app->authManager->add($permit);

Yii не проверяет сам права. Имя «deleteUser» — просто строка, она никак не соотносится с action и другими сущностями Yii. Проверять, имеет ли право юзер на действия вы должны сами

if(Yii::$app->user->can('deleteUser'))
...

Роли и права можно наследовать. Причем без ограничений что от чего наследуется.

$role = Yii::$app->authManager->getRole($name);
$permit = Yii::$app->authManager->getPermission($permit);
Yii::$app->authManager->addChild($role, $permit);

Те наследовать можно:

  • роль от роли
  • роль от права
  • право от роли
  • право от права

Пример: роль админа наследует все права от роли пользователя (что разрешено пользователю становится доступно админу).
Уровень вложенности наследуемых прав не ограничен. Главное не перемудрить и самому не запутаться

Привязка ролей к пользователю

Многих вводит в заблуждение поле role в таблице User. Человек меняет значение в поле и надеется на то, что Yii правильно обработает роль. А этого не происходит. Забудьте про поле role в таблице User. К RBAC оно отношения не имеет.
Назначение роли так же делается через authManager

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

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

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

У пользователя может быть несколько ролей. Получить их всех можно вот так:

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

Гибкое управление ролями в Yii2 и проверка прав «на лету»

Если вам не хочется вникать в RBAC и писать свой велосипед, можете воспользоваться моим готовым расширением. Скачать его можно с github.
Установив мой модуль вы получите:

  • готовую админку для добавления ролей и прав
  • возможность через админку связывать права с ролями
  • возможность через админку назначать роли пользователям
  • проверку прав «на лету» по понятным правилам доступа

Настраивать права с таким модулем сможет каждый, даже тот кто не понимает принципов работы RBAC в Yii2.
А если у вас остались вопросы — задавайте их в комментариях.

PS: по многочисленным просьбам в модуль добавлена страница для привязки роли к юзеру. Спасибо всем за внимание, замечания и вопросы. Жду новых пожеланий :)


Метки:

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

110 комментариев »

    Askar

    Добрый день.
    Я сейчас как раз работаю с rbac.

    Не могу найти нормальной документации или статьи что бы детальней изучить Yii2 RBAC.

    Еще когда происходит
    Yii::$app->authManager->assign($permit, $user->getId());

    то привязка записываеться в БД?

      Developer

      Да, если вы используете DbManager, то записывается в таблицу auth_assignment
      Буду признательна, если напишите какие именно моменты остались не понятными после прочтения этой статьи. Проблема всех статей в том, что пишут их люди, уже хорошо разобравшиеся в теме и в итоге некоторые вещи забывают описать, так как для них они само собой разумеющиеся. Напишите что именно не понятно, а я постараюсь объяснить.


    Askar

    Спасибо большое. В принципе все понятно за исключение некоторых тонких моментов.

    К примеру После создания роли и правила происходит такое:
    $guest->ruleName = $userGroupRule->name;

    Я так понял что к этой роли жестко привязывается правило и только это правило отвечает за доступ к определенным правам.

      Developer

      Вопроса не поняла :)
      $guest->ruleName = $userGroupRule->name;
      В этой строчке, если userGroupRule создан через Yii::$app->authManager->createPermission(), то это к полю ruleName у User присваивается имя правила. Но никак не назначается само правило для $guest. Посмотрите как используется ruleName в дальнейшем. Возможно дальше в коде оно используется для привязки прав (Yii::$app->authManager->assign) или в качестве дочернего правила (Yii::$app->authManager->addChild), а может как бизнес правило. Бизнес правила нужны для того, чтобы разрешить действие в зависимости от условий. Пример: можно редактировать комментарии, но только те, что принадлежат юзеру.


    Askar

    Забыл уточнить
    $userGroupRule = new UserGroupRule(); // бизнес правило
    $guest = $authManager->createRole(‘quest’); // Роль

    $guest->ruleName = $userGroupRule->name;

    Кусок кода я увидел тут http://habrahabr.ru/post/235485/

      Developer

      Askar, это к роли присваивается бизнес правило. Оно должно возвращать true или false, те разрешен доступ или нет.

      //Получаем группу текущего юзера
      $group = \Yii::$app->user->identity->group; 
      // Если проверяем права на admin, те было Yii::$app->user->can('admin')
      if ($item->name === 'admin') {
         // группа пользователя равна 'admin'? возвращает true или false в качестве результата проверки равенства
        return $group == 'admin';
      }
      

    Cepefagel

    Добрый день, спасибо Вам огромное за статью, это наверно самый понятный материал на тему RBAC, и идея Вашего модуля мне очень понравилась на счет проверки прав, у меня есть три роли user,manager,admin пока еще нет permission и вот на этом этапе

    		foreach($routeVariant as $r){
    			if(Yii::$app->user->can($r, $route[1])){
    				return true;
    			}
    		}
    у меня $route[1] всегда пустой массив, в конфиге у меня вот что 
    'as AccessBehavior'   => [
    		'class' => AccessBehavior::className(),
    		'rules' => [
    			'login/default' => [
    				[
    					'actions' => ['index'],
    					'allow'   => true,
    				    'roles' => ['?']
    				],
    			],
    		],
    
    	],
    

    то есть к этому адресу я могу обратиться вот таким образом backend.site.ru/login или backend.site.ru/login/default соответственно и у меня всегда недостаточно прав

      Developer

      В настройках так прописать не получится. В настройках поведения можно передать только контроллер и action. А вы пытаетесь прописать туда модуль. Поведение создает из этих данных объект класса AccessRule. У него нет параметра для модуля. Те на данный момент поведение не поддерживает правила в конфиге на уровне модуля.

      'rules' => [
      'ControllerName' => [
      [
      'actions' => ['actionName'],
      

      Что можно сделать? Прописать через админку правило для login и тогда на лету оно будет правильно проверятся. На лету умеет проверят и для контроллера и для модуля.
      По поводу $route[1]:

       $route = Yii::$app->getRequest()->resolve();
      

      $route[0] — это путь по которому вы обратились
      $route[1] — это $_GET параметры, переданные по адресу, по которому вы обратились.
      Те то что $route[1] пустой — это правильно и не влияет на работу поведения.


    Cepefagel

    получилось достучаться до login/defautl, но например написать просто login не получается, обязательно нужно указывать контроллер, страница открывается но вот теперь на панели дебагер показывает Bad Request (#400): Не достаточно прав


    Для тех, кто в танке)

    В разделе «Настройка ролей и прав» указано «Теперь нужно создать роль и сохранить ее в RBAC».
    Можете указать полный текст кода с названием файла и пути, где его сохранить для создания ролей и сохранения в RBAC?) Для шаблона Advanced.

      Developer

      В статье есть кусок кода для создания ролей. Если вам он не помог — возьмите готовый модуль: https://github.com/developeruz/yii2-db-rbac там написано куда и что прописать. А потом, когда нибудь, посмотрите код модуля и разберетесь с тем, как это работает. А пока вам достаточно будет подключить модуль и открыть оконный интерфейс для создание ролей и прав 😉 А использовать эти роли можно прописав в контроллере

       public function behaviors()
          {
              return [
                  'access' => [
                      'class' => AccessControl::className(),
      ...
      

      чтобы пока не вникать в то, как их привязать к роли.


    Руслан

    Доброго времени суток, модуль подключить удалось, создаются роли, правила, впринципе похоже на то, что все работает, работает также Yii->$app->user->can(), но когда в конфиге backend/config/main вставляю вот это
    ‘as AccessBehavior’ => [
    ‘class’ => AccessBehavior::className(),
    ],
    (кстати, вставлять нужно просто в возвращаемый массив?), выдает ошибка Invalid argument supplied for foreach() в AccessBehavior.php. Жалуется на то, что поле _rules пустое, продампил — в самом деле null. В чем может быть проблема? Заранее спасибо

      Developer

      Это баг. Исправила. Спасибо, что нашли!


    nnm

    У меня есть большая просьба к вам рассказать по-подробнее как лучше прописывать роли через консольные комманды rbac init или же через action в контроллерах.
    Ещё один вопрос. Я так понял, что в вашем модуле yii2-db-rbac нет оконного интерфейса привязки ролей к конкретным пользователям?

      Developer

      Я считаю, что жесткий харкод ролей в контроллере — это зло. Потому, что теряется гибкость. Но мне кажется вы немного путаете. Чтобы в action прописать Yii::$app->user->can() или правила для AccessControl вам все равно нужно сперва создать права в Rbac. Те нужно и создать роли и прописать их.
      Да, все верно. В моем модуле нет оконного интерфейса привязки ролей к пользователям. Там есть только подсказки, какие строки добавить в ваш модуль User, чтобы привязать роль. Я планирую сделать модуль User, но пока его нет.


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

    Не могу понять, у меня вообще нету директорий rbac и естественно migrations

      Developer

      У вас есть папка /vendor/yiisoft/yii2/rbac и в ней папка с миграциями. Просто для длинного пути vendor/yiisoft/yii2 в yii есть алиас @yii. Самому вам создавать папку rbac не нужно, если вы планируете хранить роли в БД. Она нужна только если роли вы будите хранить в файлах, но тогда миграции вам не к чему.


    Джемал

    Добрый день.
    А подскажите пожалуйста, на вашем сайте написано:
    [quote]Yii не проверяет сам права. Имя «deleteUser» — просто строка, она никак не соотносится с action и другими сущностями Yii. Проверять, имеет ли право юзер на действия вы должны сами

    if(Yii::$app->user->can('deleteUser'))
    ... 

    [/quote]
    Я делал с Вашей помощью и всё получилось, за что премного благодарен. Но остался последний вопрос:

    public function actionCreate()
        {
            $model = new totems();
    
            if ($model->load(Yii::$app->request->post()) && $model->save()) {
                return $this->redirect(['view', 'id' => $model->id]);
            } else {
                return $this->render('create', [
                    'model' => $model,
                ]);
            }
        } 

    Сейчас он дает сделать update тем кому нужно, а кому нет — показывает белый лист. А как сделать так, чтобы он показывал либо javascript предупреждение, либо какое-либо предупреждение, на обычной странице?
    Заранее спасибо за ответ.

      Developer

      Допишите в контроллере:

       public function actions()
          {
              return [
                  'error' => [
                      'class' => 'yii\web\ErrorAction',
                  ],
                  ];
          }
      

      Таким образом вы назначите action для ошибок. Тогда будет показываться ошибка, в частности «Доступ запрещен» вместо пустой страницы. Можно отнаследоваться от него и сделать свой вариант обработки ошибок.


    polumerk

    Из консоли запускаю установку модуля, командой:

    w:\domains\smsall\www>composer require developeruz/yii2-db-rbac «*»

    Выдает такую ошибку:

    Your requirements could not be resolved to an installable set of packages.

    (w:\domains\smsall\www>composer require developeruz/yii2-db-rbac «*»
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.)

    В чем может быть проблема?


    polumerk

    Справился с проблемой, прописал вот такую команду:

    composer require «developeruz/yii2-db-rbac» «dev-master»


    Александр

    Здравствуйте! Спасибо за полезную статью!
    У меня, все получилось, за исключением метода behaviors в контроллере, т.е. я описываю для ролей экшны, и в случае отказа в доступе мне выдает соответствующую страницу, но! белую, без стилей. Я прописал в actions ‘class’ => ‘yii\web\ErrorAction’, но это не помогло. В итоге я прописал в behaviors ‘actions’ => [‘error’], ‘allow’ => true, и только тогда у меня страница с ошибкой вывелась как надо, со стилями. Я что-то сделал неправильно? Или так и надо, в каждом контроллере разрешать доступ к экшну error?
    Спасибо!

      Developer

      Скорее всего в ваших правилах вы запретили доступ ко всем action в том, числе и к error. Поэтому пока вы явно не разрешили доступ к этому action (‘allow’ => true) доступа к нему у вас небыло.


    stacy_smith_ua

    Добрый день,

    index.php?r=permit/access дает ошибку 404.

    в backend/main.php в modules,
    ‘permit’ => [
    ‘class’ => ‘developeruz\db_rbac\Yii2DbRbac’,
    ],

    developeruz/yii2-db-rbac установлено.

    В чем может быть проблема? Спасибо!

      Developer

      В маршрутизации, в ваших настройках urlManager. Трудно что-то говорить без код :(


    Roman

    Привет! Есть проблема….
    В beforeAction контроллера пытаюсь делать проверку на Yii::$app->user->can(‘myPermission’), а в ответ всегда false (у текущего юзера админская роль), но как только в конфигах указываю defaultRoles со всеми существующими ролями — ситтуация меняется, права появляются на все и у всех. Все делал согласно мануалу, в базе просмотрел права у ролей не на один раз, привязка к пользователю есть.
    В чем может быть проблема?

      Developer

      defaultRoles — это роли, которые назначаются всем пользователям без assign.
      Проверьте еще раз тип authManager — если роли хранятся в БД — то нужно использовать yii\rbac\DbManager.


    Игорь

    Спасибо за статью, никак не мог понять работу rbac. Очень помогли.


    Алексей

    День добрый.

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

    Пытаюсь проверять с помощью Yii::$app->user->can(‘permissionName’). Для всех пользователей и даже гостя это выражение возвращает истину. Хотя по логике только к пользователю с ролью «admin»
    Если делаю ошибку в имени права Yii::$app->user->can(‘permissionBadName’) то возвращает лож.

    Делал так :

    //Создаем роль
    $admin = $authManager->createRole(‘admin’);
    $authManager->add($admin );

    //Создаем правило
    $permissionName = $authManager->createPermission(‘permissionName’);
    $authManager->add($permissionName );

    //добавляем правило к роли
    $authManager->addChild($admin, $permissionName );

    //Ассоциируем пользователя с ролью
    $authManager->assign($admin, 1);

    В бд все создалось корректно.

    Если делаю ошибку в имени права Yii::$app->user->can(‘permissionBadName’) то возвращает лож.

    Спасибо

      Developer

      Yii::$app->user — это текущий залогиненный юзер. Каким образом вы проверяете право для других юзеров?
      Можно проверить таким образом, чтобы не перелогиневаться каждый раз:

      $auth = Yii::$app->getAuthManager();
      if($auth->checkAccess($user->id, $permissionName))
      {
      
      }
      

      Тут у вас $user — это модель юзера, для которого вы проверяете права.


    Hidden

    Хорошее решение, взял на заметку.
    Но заметил одну проблемку :-)
    Если у нас layout имеет такой вид:

    страница всё равно будет загружена (https://yadi.sk/i/1pgo0Q10fX2gH)

    Вот здесь: https://github.com/developeruz/yii2-db-rbac/blob/master/behaviors/AccessBehavior.php#L29
    Можно заменить на: Application::EVENT_BEFORE_REQUEST => ‘interception’,
    И получится нужный результат
    https://yadi.sk/i/XR3VJ1aofX2oN


    Manaraga

    исходный код

    1 $userRole = Yii::$app->authManager->getRole(‘name_of_role’);
    2 Yii::$app->authManager->assign($userRole, $user->getId());

    $user откуда вылез? Где-то выше было $user = Yii::$app->user ?

      Developer

      Подразумевается, что где-то выше вы уже нашли нужного юзера по логину/паролю например или по id, те в $user у вас находится модель юзера, которому вы хотите присвоить роль. Yii::$app->user можно использовать только если роль вы хотите присвоить текущему залогиненному юзеру.


    Дмитрий

    Здравствуйте =)
    Не получается настроить миграции. А где можно взять SQL дамп структуры таблицы и данных?) нет ли где-нибудь SQL запроса. Спасибо за уделенное внимание!

      Developer

      Мой модуль таблиц не имеет, использует таблицы DB менеджера Yii. Вот его миграция в формате SQL

      drop table if exists `auth_assignment`;
      drop table if exists `auth_item_child`;
      drop table if exists `auth_item`;
      drop table if exists `auth_rule`;

      create table `auth_rule`
      (
      `name` varchar(64) not null,
      `data` text,
      `created_at` integer,
      `updated_at` integer,
      primary key (`name`)
      ) engine InnoDB;

      create table `auth_item`
      (
      `name` varchar(64) not null,
      `type` integer not null,
      `description` text,
      `rule_name` varchar(64),
      `data` text,
      `created_at` integer,
      `updated_at` integer,
      primary key (`name`),
      foreign key (`rule_name`) references `auth_rule` (`name`) on delete set null on update cascade,
      key `type` (`type`)
      ) engine InnoDB;

      create table `auth_item_child`
      (
      `parent` varchar(64) not null,
      `child` varchar(64) not null,
      primary key (`parent`, `child`),
      foreign key (`parent`) references `auth_item` (`name`) on delete cascade on update cascade,
      foreign key (`child`) references `auth_item` (`name`) on delete cascade on update cascade
      ) engine InnoDB;

      create table `auth_assignment`
      (
      `item_name` varchar(64) not null,
      `user_id` varchar(64) not null,
      `created_at` integer,
      primary key (`item_name`, `user_id`),
      foreign key (`item_name`) references `auth_item` (`name`) on delete cascade on update cascade
      ) engine InnoDB;


    fire-bug

    При том, что vendor\developeruz\db_rbac\Yii2DbRbac.php существует, вылетает ошибка

    Class developeruz\db_rbac\Yii2DbRbac does not exist

      Developer

      Класс есть, но нет автозагрузки этого класса. Скорее всего вы скачали модуль не через композер. Так не хорошо делать, но сработает: лезем в папку vendor/composer/autoload_psr4.php и дописываем

      'developeruz\\db_rbac\\' => array($baseDir . '/'),

      Не уверена в том, что композер не перезатрет это снова. Так что настоятельно рекомендую разобраться с композером. Без него в yii будет сложно.


    fire-bug

    При попытке установки вылетает ошибка:
    D:\OpenServer\domains\lk-ia>composer require developeruz/yii2-db-rbac «*»
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.

    Problem 1
    — The requested package developeruz/yii2-db-rbac could not be found in any v
    ersion, there may be a typo in the package name.

    Potential causes:
    — A typo in the package name
    — The package is not available in a stable-enough version according to your min
    imum-stability setting
    see f
    or more details.

    Read for further common
    problems.

    Installation failed, reverting ./composer.json to its original content.

      Developer

      Это потому, что у моего репозитория нет стабильной версии. Надо бы исправить. А пока запускайте так
      composer require developeruz/yii2-db-rbac "dev-master"


    Elena

    Добрый день! А как потом получить роли и права пользователя? Если делаю вот так: Yii::$app->authManager->getPermissionsByUser(Yii::$app->user->id)

    То пусто. Хотя пользователю присвоила право напрямую. Это право у меня появляется, когда получаю все роли пользователя.
    Как быть?

      Developer

      Вы путаете роли и permission. Есть два метода getPermissionsByUser() и getRolesByUser(). Если вы назначили пользователю разрешение как роль, то и получать ее нужно через getRolesByUser().


    des

    допишите уже вид для привязки пользователей к ролям

      Developer

      Проблема в том, что класс User у всех свой. Как определить, какое поле использовать как id юзера, а какое в качестве отображаемого имени (login, username, last_name.’ ‘.name)? Вторая проблема — логическое разделение ролей: бывают системы, где у юзера должно быть не более 1 роли, бывают где права используются вместо ролей, бывает что некоторые роли содержат доп-привилегии, которые нужно кастомно выводить во вьюшке. И присвоение ролей не у всех идет через админку. Но просьбу такую слышу уже не в первый раз и простой модуль для привязки ролей постараюсь сделать, как будет время. Следите за обновлениями :)


    Takhir

    Добрый день!
    Спасибо за статью, только вот совсем новичкам думаю не совсем понятен будет ваш пост, так как они не имеют представление где подключать authManager (в каком файле), где создавать роль и сохранить ее в RBAC и т.д.

      Developer

      Yii — это фреимворк и он не предназначен для не программистов. Если вам сложно разобраться в каком файле находится конфиг, возьмите лучше готовую CMS, тот же WordPress. Дальше будет еще сложнее и в сети информацию по шагам и файлам найти будет очень сложно. Статья для программистов, совсем начинающим, не знакомым с Yii и принципами ООП в целом она не поможет, в этом вы абсолютно правы.


    Роман

    Добрый день я писал вам на почту о своей проблеме о данном модуле.
    Все работает все летает но пробую ставить проверку на лету
    поместил
    use developeruz\db_rbac\behaviors\AccessBehavior;
    //в поведение прописал
    public function behaviors()
    return [
    ‘as AccessBehavior’ => [
    ‘class’ => AccessBehavior::className(),
    ],
    yii2 выдает

    Getting unknown property: backend\controllers\ManagerController::requestedAction

      Developer

      Да, после одного из обновлений модуль поломался. Сейчас все уже работает, ошибка исправлена.


    Nikolay

    Почему в AccessBehavior.php вы кидаете BadRequestHttpException exception?

    throw new BadRequestHttpException(‘Не достаточно прав’);

    Мне кажется правильнее будет кинуть ForbiddenHttpException

      Developer

      Да, вы правы, нужен фобиден.


    Алексей

    Если мы используем phpmanager, где хранятся данные о том, какой пользователь принадлежит какой роли?

      Developer

      Если вы используете PhpManager, то все данные хранятся в файлах, указанных в настройках PhpManager-а:
      itemFile — для хранения ролей и permission
      assignmentFile — для хранения связей пользователей и ролей
      ruleFile — для хранения бизнес правил.
      По умолчанию $assignmentFile = ‘@app/rbac/assignments.php’ Учитите, что для файла нужно дать права на запись.


    Дмитрий

    Добрый день. Подскажите пожалуйста, решение такой проблемки: при миграции (yii migrate —migrationPath=@yii/rbac/migrations/) выбрасывает исключение — You should configure «authManager» component to use database before executing this migration. Однако authManager прописан в компонентах (
    ‘authManager’ => [
    ‘class’ => ‘yii\rbac\DbManager’,
    ],
    ).
    Спасибо

      Developer

      Скорее всего он у вас прописан в компонентах веб приложения, но не указан в конфиге консольного приложения (для base приложения: прописан в web.php но не прописан в console.php)


    Max

    Спасибо большое, отличный мануал. Все четко и понятно.


    human

    Большое спасибо за Ваш блог! Начинаю изучать yii2 и более «легких» и понятных статей еще не видел. А главное все работает после них =)

      Developer

      Большое спасибо за такие теплые слова :) После таких отзывов так и хочется написать еще что-нибудь полезное :)


    mihacoder

    Привет! Присоединяюсь к предыдущему комменту — написано очень хорошо, в сочетании с родной документацией все становится ясно с первого раза. Спасибо!

      Developer

      Спасибо вам за теплый отзыв :)


    etcoder

    У вас не совсем корректно написано про assign.
    «`
    Yii::$app->authManager->assign($permit, $user->getId());
    «`

    $permit — разрешение на какое-то действие. По правильному его нужно привязывать к роли, а вот роль уже назначать пользователю. Так того требует спецификация RBAC.

    Про наследование тоже чуточку не правильно:
    «`
    Те наследовать можно:
    роль от роли
    роль от права
    право от роли
    право от права
    «`

    По спецификации правильно наследовать только роль от роли.

    спецификация доступна по http://csrc.nist.gov/rbac/sandhu-ferraiolo-kuhn-00.pdf
    Yii2 использует Hierarchical RBAC

      Developer

      Согласна. «Правильно» наследовать роль от роли, но реализацию Yii позволяет наследовать что угодно от чего угодно. И иногда это помогает сделать настройку прав более тонко, не создая лишние сущности.


    DarkLight

    Здравствуйте, не представляете как помогли, СПАСИБО ОГРОМНОЕ!!!! Именно после прочтения Вашей статьи всё встало вдруг на свои места)))))

      Developer

      Спасибо :)


    lorem

    Здравствуйте.
    Хотелось бы поинтересоваться, занимаетесь ли вы преподаванием?
    В частности хотелось бы глубже изучить ООП PHP на практике. В дальнейшем для разработки приложений на yii2. Простые приложения на yii2 делать научился, но чувствуется, что глубины знаний ООП недостаточно.

      Developer

      Нет, преподаванием я не занимаюсь. По теории ООП могу порекомендовать книгу Гради Буча, а практика придет с опытом. Обычно с болезненным опытом :) ООП нужно прочувствовать на своей шкуре и тогда начнешь ценить и наследование и инкапсуляцию.
      Если есть конкретные вопросы — пишите, постараюсь помочь.


    Сашк0

    Привет подскажи как цивилизованным путем к таблицам из миграции:
    php yii migrate —migrationPath=@yii/rbac/migrations/
    Присвоить префикс для таблиц базы данных, а то как то не феншуйнинько смотрится, все таблицы с префиксом кроме эти четырех, да я задрот, душа лежит к идеализму, и идиллии, а эти таблицы без префикса меня выводят.
    (ручками приписать префикс тоже не феншуйнинько)
    Спасиб

      Developer

      Смотрим в код миграции:
      $this->createTable($authManager->ruleTable,
      Т.е название таблиц он берет из настроек authManager-а. Префиксы там не предусмотрены, значит есть 2 варианта:
      1) Просто прописываем таблицы ручками в конфиге

       'authManager' => [
                  'class' => 'yii\rbac\DbManager',
                  'itemTable' => Yii::$app->params['table_prefix'].'_auth_item' 
      //тоже самое для itemChildTable, assignmentTable, ruleTable
              ],
      

      2) Решение для перфекциониста: переопределить DbManager, отнаследовав его от настоящего и дописать там использование префикса. И тогда конфиг будет выглядить как-то так:

       'authManager' => [
                  'class' => 'path_to_my\DbManager',
                  'prefix' => Yii::$app->params['table_prefix']
              ],
      

      Если очень хочется — то нет ничего не возможного :)


    Дмитрий

    В представленом готовом модуле отсутсвует контроль доступа к страницам модуля.
    Конечно вписать пару строк кода не сложно но ведь кто то может воспользоваться неглядя.

      Developer

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


    Сергей

    Добрый день! Подскажите в каком файле, что надо править, для того чтобы запретить все, что не разрешено?
    Спасибо! Отличная статья, со всем разобрался, остался только вопрос, как закрыть доступ к модулю к ссылкам /permit/access/role , /permit/access/permission , /permit/user/view/ .


    Сергей

    Разобрался:
    в vendor/developeruz/yii2-db-rbac/controllers/AccessController.php
    добавил
    public function behaviors()
    {
    return [

    ‘as AccessBehavior’ => [
    ‘class’ => AccessBehavior::className(),
    ],

    ];
    }
    ну и соотв доступ настроил в Правилах доступа permit и разрешил только роли admin

      Developer

      Не хорошо править что-то в папке vendor: во-первых ваши правки затрутся при обновлении версии модуля в композере, во вторых если вы используете систему контроля версий, вся папка vendor игнорируется и ваши правки не попадут в репозиторий.
      Я рекомендую настроить поведение на уровне приложения, т.е прописать в конфиге:

       'components' => [...],
       'as AccessBehavior' => [
              'class' => AccessBehavior::className(),
      // настраиваем права тут
       ]
      

    Сергей

    Добрый день! Есть еще вопрос. У меня подключен модуль RESTApi. Находится в папке backend/modules/api_v1. В нем папка с controllers WorkControllers.php, ProfileController.php. — behaviors не прописаны в контроллерах.
    Мне нужно чтобы доступ к api_v1 был разрешен абсолютно всем!
    Запросы отправляются в таком виде http://backend.site.loc/api_v1/profile , http://backend.site.loc/api_v1/work

    В конфиге приложения прописано — вроде работает. Можно ли как-то оптимизировать:

    'as AccessBehavior' => [
            'class' => AccessBehavior::className(),
            'rules' =>
                [
                    'api_v1/profile' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
                    'api_v1/works' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
                    'api_v1/skills' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
                    'api_v1/personal-info' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
                    'api_v1/experience' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
                    'api_v1/education' =>
                        [
                            [
                                'allow' => true,
                            ]
    
                        ],
    
        ],
    
      Developer

      Оптимизировать в конфиге не получится, но можно через интерфейс модуля задать правило «api_v1/*» и привязать его к роли по умолчанию (в конфиге прописать что у любого юзера на сайте по умолчанию такая-то роль, должно работать и для не авторизованных юзеров).


    Сергей

    Здравствуйте! Спасибо за ответ! Вы рекомендовали прописать роль по умолчанию в конфиге.
    Я сделал так. Добавил в common/conf/main.php

     dirname(dirname(__DIR__)) . '/vendor',
        'components' => [
            'cache' => [
                'class' => 'yii\caching\FileCache',
            ],
            'authManager' => [
                'class' => 'yii\rbac\DbManager',
                'defaultRoles' => ['user'],
            ],
        ],
    ];
    

    Создал нового пользователя user2 здесь site.loc/index.php?r=site%2Fsignup.
    Но как я понял ему не присвоилась роль user, т.к. в таблице auth_assignment его не появилось.
    Правильно ли я добавил рол по умолчанию?

      Developer

      Роль по умолчанию присваивается «на лету», если прописать в базу, а потом поменять конфиг — роль останется. Вы можете проверить присвоилась ли роль, получив все роли юзера:

      $rolesForUser = Yii::$app->authManager->getRolesByUser($id);
      

      или проверив права:

      if(Yii::$app->user->can('myRoleName')){
      echo 'Роль присвоена';
      }
      

    Юлия

    И еще вопросик.
    После выполнения миграции создалось 4 таблицы. 3 из них мне понятно зачем.
    Зачем нужна таблица auth_rule?

      Developer

      Это «бизнес правила», их трудно стандартизировать, поэтому в моем модуле они не участвуют


    АндрейК

    Привет! Большое спасибо! Реально везде столько не нужной мути намешано в кучу, а у Вас все по делу, коротко и ясно.


    Fisher

    Как для гостя прописать правила, то есть аналог «?» в стандартном RBAC?

      Developer

      Задать роль по умолчанию в настройках компонента authManager (в конфиге)

          'authManager' => [
              // ...
              'defaultRoles' => ['guest']
          ],
      

      Тогда роль guest будет присвоена любому пользователю на сайте, даже не авторизованному. И прописываем правила для этой роли, как для любой другой.


    Ренат

    Добрый день

    А права на сам модуль не работают?
    Могу ограничить все что угодно кроме доступа к самомому модулю редактирования прав.

      Developer

      Поведение специально создано для того, чтобы можно было ограничивать доступ к любым сторонним модулям, там где нельзя залезть в контроллет и дописать AccessControl. Так что и к модулю редактировани прав можно ограничить доступ, установив динамическое поведение.


    Ренат

    Прошу прощения
    но ничего не могу понять
    пытаюсь добавить права говорит нет такого класса
    добавляю следущее в конфиг main.php
    Yii2 advanced template

            'as AccessBehavior' => [
                    'class' => AccessBehavior::className(),
                    'rules' =>
                        ['access' =>
                            [
                                [
                                    'actions' => ['role','add-role','update-role','delete-role','add-permission', 'delete-permission', 'permission', 'update-permission'],
                                    'allow' => true,
                                    'roles' => ['admin'],
                                ],
                            ]
                        ]
            ],
    
      Developer

      Допишите в начале файла «use developeruz\db_rbac\behaviors\AccessBehavior»


    pa21

    «Я буду описывать тот, что хранит свои данные в БД, тк он дает больше возможностей динамически добавлять и менять роли» — в статье не слово про динамически изменяемые данные, только код для админки, не понятны связи этого кода с бд. И как я зайду с админки и добавлю новую роль на редактирования нового раздела, который создан с помощью админки, без того что бы залезть в код, вопрос не раскрыт.

      Developer

      Вам не нужно лезть ни в код ни в базу. С помощью моего модуля и динамического поведения все можно настроить через пользовательский интерфейс. Связь с БД на уровне приложения настраивается в конфиге Yii приложения. Все интерфейсы для добавления роли или прав уже есть в модуле. Устанавливайте по документации и заходите на страницу /permit/access/role или /permit/access/permission


    Евгений

    Добрый день! Спасибо Вам за решение. Подскажите пожалуйста. Не могу никак попасть на страницу логина

    'modules' => [
                'user'    => [
                    'class' => 'user\Module',
                    'as AccessBehavior' => [
                        'class' => \developeruz\db_rbac\behaviors\AccessBehavior::className(),
                        'rules' =>
                            ['default' =>
                                [
                                    [
                                        'actions' => ['login', 'index'],
                                        'allow' => true,
                                    ]
                                ]
                            ]
                    ]
                ],
    ]
    
      Developer

      1) Мне кажется поведение у вас устновлено не туда. Оно у вас получилось в модуле user. Должно быть так:

      'modules' => [
      ...
      ],
      'as AccessBehavior' => [
      ...
      ]
      

      2) Страница логина у вас в контроллере Default ? Модуль не работает с правилами по умолчанию, нужно указывать контроллер и action для каждого отдельно.


    Freetibet

    Добрый день. Я установил ваше расширение и все настроил.
    Страницы
    /permit/access/role
    /permit/access/permission
    работают

    однако на /web/permit/user/view/1 получаю ошибку в UsersControlle
    Class ‘app\models\User’ not found

    строка 31, $user = new Yii::$app->controller->module->params[‘userClass’]();

    Как вы думаете, что я сделал не так?

      Developer

      Подозреваю, что ваш класс User имеет другой namespace. Т.е у вас в приложении нет класса app\models\User (может есть backend\models\User, посмотрите namespace в классе User). Вам нужно передать в модуль правильный класс пользователя:

      'modules' => [
              'permit' => [
                  'class' => 'app\modules\db_rbac\Yii2DbRbac',
                  'params' => [
                      'userClass' => 'app\models\User'
                  ]
              ],
          ],
      

      Подробная инструкция на русском тут: https://github.com/developeruz/yii2-db-rbac/blob/master/README.RU.md


    Freetibet

    нет, неймспейс правильный
    namespace common\models;

    В конфиге бэкенда я прописал

    'modules' => [
    'permit' => [
    'class' => 'developeruz\db_rbac\Yii2DbRbac',
    'params' => [
    'userClass' => 'app\models\User'
    ]
    ],
    ],
    'components' => [
    'request' => [
    'csrfParam' => '_csrf-backend',
    ],
    'user' => [
    'identityClass' => 'common\models\User',
    'enableAutoLogin' => true,
    'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
    ],

      Developer

      Посмотрите, в компоненте ‘user’ у вас правильно прописано: ‘common\models\User’, а в компоненте ‘permit’ написано ‘app\models\User’. Замените эту строчку на правильную и все заработает.


    Freetibet

    Большое спасибо — заработало.
    Но другой вопрос:
    для назначении роли при создании нового пользователя я прописываю в модель фронтенда singnupform

    $user = new User();
    $user->username = $this->username;
    $user->email = $this->email;
    $user->setPassword($this->password);
    $user->generateAuthKey();
    $userRole = Yii::$app->authManager->getRole('participant');
    Yii::$app->authManager->assign($userRole, $user->getId());
    return $user->save() ? $user : null;

    и получаю ошибку
    Class ‘frontend\models\Yii’ not found

    хотя в конфиге фронтенда authmanager есть

    'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => [
    ],
    ],
    'authManager' => [
    'class' => 'yii\rbac\DbManager',
    ],

    p.s. какой правильный тэг для оформления кода в вашем блоге?

      Developer

      Роль у вас не привяжется, т.к привязка идет по id, а id у user появится только после сохранения. Т.е $user->save() должен вызываться до Yii::$app->authManager->assign($userRole, $user->getId());

      Но ошибка у вас сейчас другая. Пропишите в начале файла «use Yii;». А еще рекомендую установить PHPStorm, он подсвечивает подобные ошибки и существенно упрощает жизнь.
      PS: все теги режутся, так что никакое оформление кода не пройдет. Да, сапожник без сапог это про меня :)


    Евгений

    По поводу того что модуль не должен быть в конфиге модуля.
    ‘modules’ => [
    ‘checker’ => [
    ‘as AccessBehavior’ => [
    ‘class’ => \developeruz\db_rbac\behaviors\AccessBehavior::className(),
    ‘redirect_url’ => ‘/login’,
    ]
    ],
    ],

    Вот такой подход вполне себе отрабатывает на УРА. Все вроде бы логично — на уровне модуля я ставлю поведение и поведение должно обрабатывать контроллеры модуля.

    Но вот очень бы было круто если бы в таком подходе можно было бы делать ислючения. потому что сейчас нельзя сделать этого

      Developer

      Хорошая идея, но сложно реализуемая. Может быть когда нибудь…


    влад

    подскажите плиз, как привязать правило к роли? создал правило, для него разрешение, если проверять чисто это разрешение — работает, если добавить к пользователю или к роли — не работает

      Developer

      Скорее всего вы не правильно добавляете его.
      При добавлении к юзеру нужно убедиться что юзер сохраненый, т.е у него уже есть id

      $userRole = Yii::$app->authManager->getRole('name_of_role');
      //тут $user - объект сохраненного в базе юзера, иначе $user->getId() вернет null
      Yii::$app->authManager->assign($userRole, $user->getId());
      

      При добавлении к роли нужно убедится что и роль и разрешение являются объектами

      $role = Yii::$app->authManager->getRole($name);
      $permit = Yii::$app->authManager->getPermission($permit);
      // тут $role и $permit НЕ просто имя роли или разрешения
      Yii::$app->authManager->addChild($role, $permit);
      

    влад

    а планируется в вашем решении rbac включить работу с правилами?

      Developer

      Планируется, как только найду время. Но я всегда рада pull request-ам :)


    Николай

    Добрый день.
    Пару дней назад, обновил модуль и появилась ошибка.
    Invalid argument supplied for foreach()
    in /var/www/yii2_test/vendor/yiisoft/yii2/base/Component.php at line 645
    638 /**
    639 * Makes sure that the behaviors declared in [[behaviors()]] are attached to this component.
    640 */
    641 public function ensureBehaviors()
    642 {
    643 if ($this->_behaviors === null) {
    644 $this->_behaviors = [];
    645 foreach ($this->behaviors() as $name => $behavior) {
    646 $this->attachBehaviorInternal($name, $behavior);
    647 }
    648 }
    649 }

    Проект пишу на двух компьютерах, сначала подумал, что не правильно установил модуль, компосером, переустановка не помогла. Взял модуль с другого компьютера, все заработало.

    Получается проблема в последних обновлениях?

      Developer

      Да, я только что исправила эту ошибку. Обновитесь до версии 1.1.1. Спасибо.


    Михаил

    Не работает ограничение к модулю
    ‘permit’ => [
    ‘class’ => ‘developeruz\db_rbac\Yii2DbRbac’,
    ‘params’ => [
    ‘userClass’ => ‘common\models\User’,
    ‘accessRoles’ => [‘admin’]
    ]
    ]
    роль доступа — админ, но пользоваться модулем могут даже незалогиненые пользователи

      Developer

      Только что проверила еще раз — все работает. Скорее всего вы не обновили версию модуля до 1.1.1, ограничение добавлено совсем недавно, в более старой версии модуля оно не работает.


    Алексей

    А как установить этот модуль без использования композера? Скачал архив, не пойму что куда класть, в какие папки.
    Заранее извиняюсь за ламерский вопрос.. тока начинаю осваивать премудрости программирования..

    Версия yii2 basic. Вручную пытаююсь, потому что через композер установить не получается. Юзаю Openserver, в консоли опенсервера в папке проекта пишу:
    «php composer require developeruz/yii2-db-rbac «*»»
    Мне выдает:
    «could not open input file composer»
    Как то так.

      Developer

      Вам нужно поставить сперва сам композер. И я настоятельно рекомендую это сделать. Работать с Yii без композера будет тяжело. Все обновления придется делать в ручную, 100% пакетов Yii расчитаны на установку через композер.
      Если хотите делать все в ручную, то нужно устанавливать в папку vendor и прописывать autoload (у меня в папке vendor/composer/autoload_psr4.php прописаны все namespace: ‘developeruz\\db_rbac\\’ => array($vendorDir . ‘/developeruz/yii2-db-rbac’),) или подключать классы самостоятельно там где их используете (require/include_once)


    Дмитрий

    Доброго времени суток!

    Подскажите, как запретить доступ к рбак меню?
    Получается, только если в \vendor\mdmsoft\yii2-admin\controllers\*.php

    прописать

    public function behaviors() {
    return [
    ‘access’ => [
    ‘class’ => \yii\filters\AccessControl::className(),
    ‘rules’ => [
    [
    ‘allow’ => true,
    ‘roles’ => [‘admin’]
    ],
    ],
    ],
    ];

    Как это сделать не залезая в вендор?

    Спасибо

      Developer

      Установить мой Rbac модуль и настроить разграничение прав через поведение.

       'as AccessBehavior' => [
              'class' => \developeruz\db_rbac\behaviors\AccessBehavior::className(),
              'rules' => [
      'module/controller' => [[
                              'allow' => true,
                              'roles' => ['admin']
                          ]],
      ]
      

      В вендоре ничего менять нельзя, т.к все изменения перезатрутся после обновления пакетов. Если очень хочется то можно отнаследоваться и переопределить методы так как нужно. Мой модуль проверяет права «на лету», чтобы не приходилось переопределять каждый пакет.


    Виталий

    Пишет ошибку Class ‘app\controllers\Yii’ not found
    и показывает что ошибка
    в строке $name = Yii::$app->user->identity->username;
    Что не так? В файле контроллера самого yii2 c названием SiteController такие же подключения:
    use yii\filters\AccessControl;
    use yii\filters\VerbFilter;
    use yii\web\Response;
    и еще есть другие,
    но actionLogin в данном контроллере работает,
    в actionLogin тоже есть команда $model = new LoginForm();
    if (!Yii::$app->user->isGuest) {
    return $this->goHome();
    }
    }
    То есть конструкция Yii::$app->isGuest работает, почему тогда в моем файле не работает конструкция Yii::$app->user->identity->username
    Очень интересно узнать в чем причина

      Developer

      Причина в namespace, не существует класса app\controllers\Yii, допишите в начале файла use Yii и обязательно почитайте про namespace, сбережет много сил в будущем.


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









Копирование материалов разрешено при наличии активной ссылки на источник
Яндекс.Метрика