Yii Framework 2.0 基于角色的访问控制 RBAC

Posted

技术标签:

【中文标题】Yii Framework 2.0 基于角色的访问控制 RBAC【英文标题】:Yii Framework 2.0 Role Based Access Control RBAC 【发布时间】:2014-12-26 10:07:51 【问题描述】:

学习 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()方法时,上面的数据库表已经根据上面的代码填充了数据。此外,在我的用户表中,我有两个用户,管理员用户的 ID 号为 1,作者用户的 ID 号为 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 解释来弄清楚。

【问题讨论】:

什么是难懂的? 按照文档yiiframework.com/doc-2.0/guide-security-authorization.html 我无法让它与 updateOwnPost 一起使用,并且不知道如果您访问链接,访问检查部分下的变量 $post 的值是什么。如果您能提供帮助,我们将不胜感激! 这就是 $post 模型。你能编辑你的问题,用具体的术语问你想要的东西,解释你做了什么,以便给出具体的解决方案吗? 我刚刚编辑了我的问题,包括我到目前为止所做的事情以及我卡在哪里。 【参考方案1】:
if (\Yii::$app->user->can('updatePost', ['post' => $post])) 
    // update post 

在我的脚本中,我将$post 更改为$model

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

然后就可以了。

【讨论】:

【参考方案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

所有这些都来自指南。 如果您有任何问题,请告诉我

【讨论】:

你的文字下的代码:'add it in your RBAC role',放在我的RbacController的actionInit()方法里? 我可以使用上述检查任何型号的帖子吗?我还是不明白它是怎么知道这个检查是关于哪个模型的。 您不想签入模型。检查应该在控制器操作中完成,而不是在模型中 如果它的控制器范围使用 beforeAction/init 方法并且如果它用于单个操作,请在执行任何受保护的指令之前检查顶部 'post' 这个名字在这里重要吗($param[] 中的键),或者它适用于除了 postController 之外的任何其他控制器?我假设 updatePost 的关联数组必须与给定键的名称匹配,但它适用于 Post 以外的任何模型。我错了吗?

以上是关于Yii Framework 2.0 基于角色的访问控制 RBAC的主要内容,如果未能解决你的问题,请参考以下文章

如何在 yii 中创建访问(查看页面)角色?

Yii2 RBAC权限

Yii 2.0 GII 访问404错误

讲堂 | Yii2之rbac(基于角色的权限管理)-- 思想与配置

Yii2 角色和用户

yii 2.0 属性