基于 yii2 RBAC 权限管理全解

相信大家对 RBAC 权限控制都比较了解。我们来

下面是摘自 yii 权威指南中关于 RBAC 权限控制的介绍

基本概念
角色是 权限 的集合 (例如:建贴、改贴)。一个角色 可以指派给一个或者多个用户。要检查某用户是否有一个特定的权限, 系统会检查该包含该权限的角色是否指派给了该用户。

可以用一个规则 rule 与一个角色或者权限关联。一个规则用一段代码代表, 规则的执行是在检查一个用户是否满足这个角色或者权限时进行的。例如,"改帖" 的权限 可以使用一个检查该用户是否是帖子的创建者的规则。权限检查中,如果该用户 不是帖子创建者,那么他(她)将被认为不具有 "改帖"的权限。

角色和权限都可以按层次组织。特定情况下,一个角色可能由其他角色或权限构成, 而权限又由其他的权限构成。Yii 实现了所谓的 局部顺序 的层次结构,包含更多的特定的 树 的层次。 一个角色可以包含一个权限,反之则不行。(译者注:可理解为角色在上方,权限在下方,从上到下如果碰到权限那么再往下不能出现角色)

配置

知道概念之后我们可以开始配置我们 Yii 中关于 RBAC 的组件authManager

return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\DbManager',
            //'class'=>'yii\rbac\PhpManager',
        ],
        // ...
    ],
];

这之中我们的 yii 给我们提供了两套授权方案

DbManager把授权数据存贮在数据库中

PhpManager 使用 PHP 脚本存取授权数据

如果我们是一个小网站(意味着我们的角色和权限改动很小),我们应该选取 php 脚本存储

配置中的可选项

cache => 开启 RBAC 缓存,用于提高 RBAC 性能(如果没有设置则代表缓存没有开启)

cacheKey => 缓存的密钥(默认值 ‘rbac’ )

db => 数据库连接对象(默认值 db )

itemChildTable 指定存储 auth_item_child (存放权限或用户的子节点数据表) 的表名称 (默认值 ‘{{%auth_item}}’)(%表示表前缀)

ruleTable 同理存放规则名称数据库(默认值为 ‘{{%auth_rule}}’ )

assignmentTable 同理

itemTable同理

注: 在 basic 模板下我们要在 config/web.phpconfig/console.php 中配置,在 advanced 中,只能在 common/config/main.php 中声明一次 (这段话是出自权威指南的上话,但笔者亲测在 advanced 模板中 backend 和 frontend 中都可以配置)

建立授权关系

在建立授权关系时,我们需要有以下 4 张表

  • itemTable: 该表存放授权条目(译者注:即角色和权限)。默认表名为 “%auth_item” 。
  • itemChildTable: 该表存放授权条目的层次关系。默认表名为 “%auth_item_child”。
  • assignmentTable: 该表存放授权条目对用户的指派情况。默认表名为 ” %auth_assignment”。
  • ruleTable: 该表存放规则。默认表名为 “%auth_rule”。

所以我们需要去数据库中建立上面 4 张表。

不过 yii 已经为我们建立了上面四张表的模板。我们可以用 @yii/rbac/migrations 目录中的数据库迁移文件来做这件事

在 yii 根目录下使用命令./yii migrate --migrationPath=@yii/rbac/migrations(后面我会出一篇有关 yii 数据迁移的笔记)

执行完命令,我们四张表就建立完成了。我们就可以使用Yii::$app->authManager来访问我们的 authManager 组件了

authManager 可用方法



addChild($parent,$child) //给该授权增加一个子项 (授权可用是规则,也可以是角色)

assign($role,$userId) //给用户分配一条权限或用户组

canAddChild($parent,$child)//检查能否将子节点添加到父节点中去。(返回 bool)

/*创建权限或者数据*/

createPermission($name)//返回一个权限规则的实例

createRole($name)//返回一个名字为 '$name' 的角色实例

add($object) //添加一个角色,权限,规则到 auth_item 表,$object 可以为上面几个 create 返回的方法

getChildren($name)//根据 name 查找它的子用户或者子权限

getRoles()//以数组的形式返回所有的角色

getPermissions()//返回所有的权限规则信息以数组的形式返回

removeChildren($parent)//把该父类的全部子节点的依赖关系删除

removeChild($parent,$child)//删除指定的子节点和父节点的依赖关系

remvokeAll($uid)//解除 用户-用户组 的关系

getAssignments($uid)//获取所有的用户权限

getPermissionsByUser($userId)//返回该用户所有的规则

getRolesByUser($userId)//返回该用户对应的角色。

添加我们的角色

我们随便添加一条

$auth = Yii::$app->authManager; //获取我们的 authManager 组件

$obj = $auth->createRole(' 普通管理员 ');//添加角色名称
    $obj->description = ' 没有实权的管理 ';//添加角色描述
    $auth -> add($obj);

然后我们就可以在数据库中看到我们的插入的数据了

当然,如果我们看他不爽,我们也是可以把它删除的。

$obj = $auth->createRole(' 普通管理员 ');//添加角色名称
$auth -> remove($obj);//删除该管理

为该角色分配权限

 $auth->assign($obj,$adminUid);//把我们$obj 角色分配给$uid 用户

其中 o b j adminUid 是分配的用户 id

创建我们的规则

$obj = $auth->createPermission('category/del');//创建分类删除功能

$auth->add($obj);

将我们的规则添加到用户组下

$auth->addChild($auth->getRole(' 分类管理员 '),$obj)//将我们上面创建的分类删除权限分配给分类管理员

我们一个简单的 RBAC 创建好了,现在我们开启我们的认证.

①简单的在 ACF 中验证静态

//我们在控制器下的 behavious 写下我们的访问限制
 public function behaviors()
    {
        return [
            // 访问过滤控制器
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['add', 'delete', 'update', 'select'],
                'rules' => [
                    // category' 角色的访问授权
                    [
                        'allow' => true,//允许我们
                        'actions' => ['del'],
                        'roles' => ['category'],
                    ],
                ],

            ],
        ];

这种验证方式,如果我们需要改动,我们需要改动很多地方。例如我们要取消分类管理员的删除分类的权限,就很麻烦。

所以我们引入了动态验证

②动态的授权管理

这个和我们静态验证的区别是,我们可以根据数据库中的角色,来动态管理该授权

代码实例

class BaseController extends Controller
{
    public function beforeAction($action)
    {
        if(!parent::beforeAction($action))
        {
            return false;//如果父类验证失败,则返回失败
        }

        $permission = $action->controller->module->requestedRoute;//记录我们访问的规则名称
        if(Yii::$app->user->can($permission))
        {
            return true;//如该用户能访问该请求,则进行返回
        }

         throw new UnauthorizedHttpException(' 你没有该权限 ');//如果没有该权限,抛出一个异常
    }
}

我们下面只需要在我们需要限制访问的控制器中继承该方法即可。

拓展

如果我们之中需要做到文章管理员只能删除自己创建的文章,不能删除其他人创建的文章,我们如何做到对他的权限判断呢?

Yii 为我们提供了一套精准的判断方法

使用 rules 精准认证每一条数据

class AuthorRule extends Rule
{
    public $name = 'isAuthor';

    public function execute($user, $item, $params)
    {
        $action = \Yii::$app->controller->action->id;//获取当前的动作名称

        if ($action=='delete')//如果该动作为删除则验证是否能够删除
        {
            $article = Article::findOne(\Yii::$app->request->get('id'));
            $author = $article->userid;
            if ($author==\Yii::$app->user->id)
            {
                return true;
            }
            return false;
        }
    }
}

控制器中的方法

public function actionCreaterule()
    {
        if (\Yii::$app->request->isPost)
        {
            $name = \Yii::$app->request->post('class_name');
            $class = 'common\models\\'.$name;
            if (!class_exists($class))
            {
                throw  new NotFoundHttpException('该规则类不存在');
            }
            $rule = new $class;
            if (\Yii::$app->authManager->add($rule))
            {
                \Yii::$app->session->setFlash('info','添加成功');
            }
        }
        return $this->render('createrule');
    }

这样在我们为角色分配了权限之后,访问的时候,自动执行我们的方法

猜你喜欢

转载自blog.csdn.net/qq_36172443/article/details/80341808
今日推荐