Yii Framework 2.0 Управление доступом на основе ролей RBAC

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

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

Я создал таблицы базы данных с помощью следующего скрипта sql.

drop table [auth_assignment];
drop table [auth_item_child];
drop table [auth_item];
drop table [auth_rule];

create table [auth_rule]
(
    [name]  varchar(64) not null,
    [data]  text,
    [created_at]           integer,
    [updated_at]           integer,
    primary key ([name])
);

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
);

create index [idx-auth_item-type] on [auth_item] ([type]);

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
);

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
);

Я построил данные аутентификации следующим образом.

class RbacController extends Controller
{
    public function actionInit()
    {
        $auth = Yii::$app->authManager;

        // add "createPost" permission
        $createPost = $auth->createPermission('createPost');
        $createPost->description = 'Create a post';
        $auth->add($createPost);

        // add "updatePost" permission
        $updatePost = $auth->createPermission('updatePost');
        $updatePost->description = 'Update post';
        $auth->add($updatePost);

        // add "author" role and give this role the "createPost" permission
        $author = $auth->createRole('author');
        $auth->add($author);
        $auth->addChild($author, $createPost);

        // add "admin" role and give this role the "updatePost" permission
        // as well as the permissions of the "author" role
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $updatePost);
        $auth->addChild($admin, $author);

        // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
        // usually implemented in your User model.
        $auth->assign($author, 2);
        $auth->assign($admin, 1);
    }
}

При доступе к этому методу actionInit () через этот контроллер указанные выше таблицы базы данных были заполнены данными на основе приведенного выше кода. Кроме того, в моей таблице пользователей у меня есть два пользователя, пользователь admin имеет номер идентификатора 1, а пользователь-автор имеет номер идентификатора 2. Я использую следующий код для создания пользователя.

public function create()
{
    if ($this->validate()) {
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        $user->save(false);

        // the following three lines were added:
        $auth = Yii::$app->authManager;
        $authorRole = $auth->getRole('author');
        $auth->assign($authorRole, $user->getId());

        return $user;
    }

    return null;
}

С приведенным выше кодом все новые добавленные пользователи будут авторами. С помощью приведенных ниже операторов if я могу предоставить или запретить доступ.

if (\Yii::$app->user->can('createPost')) {
    // create post
}

if (\Yii::$app->user->can('updatePost')) {
    // update post
}

Все идет нормально. Все нормально работает. Сценарий приведенного выше кода заключается в том, что обычный автор может создавать сообщения, но не может обновлять сообщения. Администратор может обновлять пост и делать все, что может делать автор. Теперь я хочу, чтобы нормальный автор мог обновлять свой пост. Я не знаю, как дальше двигаться дальше. Я следил за параграфом Документация / Безопасность / Авторизация в руководстве Yii Управление доступом на основе ролей (RBAC). Я никогда не использовал Yii 1. Вот почему я не мог разобраться с таким кратким объяснением документации Yii 2.0 RBAC.


person O Connor    schedule 30.10.2014    source источник
comment
что сложно понять?   -  person Stefano Mtangoo    schedule 30.10.2014
comment
Следуя документации yiiframework.com/doc-2.0/guide-security-authorization .html Мне не удалось заставить его работать с updateOwnPost, и я не знаю, каким будет значение переменной $ post в разделе Access Check, если вы перейдете по ссылке. Очень признателен, если вы можете помочь!   -  person O Connor    schedule 30.10.2014
comment
Что ж, это модель $ post. Можете ли вы отредактировать свой вопрос, чтобы задать то, что вы хотите, конкретными словами, объяснив, что вы сделали, чтобы было дано конкретное решение?   -  person Stefano Mtangoo    schedule 31.10.2014
comment
Я только что отредактировал свой вопрос, указав, что я сделал до сих пор и где застрял.   -  person O Connor    schedule 31.10.2014


Ответы (2)


Вам нужно правило доступа, и документы ясны, поэтому создайте его, как

namespace app\rbac;

use yii\rbac\Rule;

/**
 * Checks if authorID matches user passed via params
 */
class AuthorRule extends Rule
{
    public $name = 'isAuthor';

    /**
     * @param string|integer $user the user ID.
     * @param Item $item the role or permission that this rule is associated with
     * @param array $params parameters passed to ManagerInterface::checkAccess().
     * @return boolean a value indicating whether the rule permits the role or permission it is associated with.
     */
    public function execute($user, $item, $params)
    {
        return isset($params['post']) ? $params['post']->createdBy == $user : false;
    }
}

затем добавьте его в свою роль RBAC

$auth = Yii::$app->authManager;

// add the rule
$rule = new \app\rbac\AuthorRule;
$auth->add($rule);

// add the "updateOwnPost" permission and associate the rule with it.
$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);

// "updateOwnPost" will be used from "updatePost"
$auth->addChild($updateOwnPost, $updatePost);

// allow "author" to update their own posts
$auth->addChild($author, $updateOwnPost);

Наконец, назначьте роль пользователю при регистрации

$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $userid_here);

чтобы проверить, есть ли у пользователя возможность редактировать, используйте код ниже, где $ post - это Модель для сообщений

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post
}

Все это взято из руководства. Сообщите мне, если у вас возникнут проблемы

person Stefano Mtangoo    schedule 30.10.2014
comment
Код под вашим текстом: «Добавьте его в свою роль RBAC», поместите его в мой RbacController в методе actionInit ()? - person O Connor; 01.11.2014
comment
Могу ли я использовать вышеуказанную проверку для публикации любой модели? Я до сих пор не понимаю, откуда он знает, о какой модели идет эта проверка. - person O Connor; 14.07.2015
comment
Вы не хотите регистрировать модели. Проверки следует выполнять в действиях контроллера, а не в моделях. - person Stefano Mtangoo; 14.07.2015
comment
Если для всего контроллера используются методы beforeAction / init и для одного действия, проверьте вверху, прежде чем выполнять какие-либо защищенные инструкции. - person Stefano Mtangoo; 14.07.2015
comment
Имеет ли значение здесь имя 'post' (ключ внутри $ param []), или оно будет работать для любого другого контроллера, кроме postController? Я предполагаю, что связанный массив для updatePost должен соответствовать имени, данному ключу, но он будет работать для любой модели, кроме Post. Я ошибся? - person jarvan; 23.01.2016

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post }

в моем скрипте я меняю $post на $model

if (\Yii::$app->user->can('updatePost', ['post' => $model])) {
    // update post }

тогда это работает.

person desktop 081    schedule 16.01.2018