Yii rbac原理和实践

  Yii框架中集成分层的 RBAC,代码位于vendor\yiisoft\yii2\rbac中,rbac工做原理分为两部分,创建受权数据和进行权限检查。php

   如上,一个角色拥有某个权限,若是但愿用户拥有这个权限,那么就将拥有该权限的角色赋予给用户,特别是当系统中用户数量很是大的时候,若是须要修改权限只须要修改角色就能够了。web

  角色和权限均可以按层次组织。特定状况下,一个角色可能由其余角色或权限构成, 而权限又由其余的权限构成。 一个角色能够包含一个权限,反之则不行。数据库

  特定的权限,能够用一个规则 rule 与一个角色或者权限关联。一个规则用一段代码表明, 规则的执行是在检查一个用户是否知足这个角色或者权限时进行的。例如,"改帖" 的权限 能够使用一个检查该用户是不是帖子的建立者的规则。权限检查中,若是该用户 不是帖子建立者,那么他(她)将被认为不具备 "改帖"的权限。yii2

  Yii中rbac的角色权限数据能够经过文件和数据库进行存放,若是是数据库存放角色权限数据,那么须要配置config目录下web.php和console.php中的authManager。下面以创建一个能够进行注册登陆发帖的而且用户只能够修改本身文章的系统为例。app

第一步:基本配置框架

              web.phpyii

            console.phpide

 

第二步:初始化数据库post

命令行中运行yii的migrate命令,须要将yii.bat所在目录添加到系统环境变量中就能够像下面这样执行了。ui

  

而后会在数据库中多出四个表,auth_item, auth_rule, auth_item_child, auth_assignment。

                auth_item表

存放权限数据,包含各个权限的名字和描述以及关联的规则,具体的字段含义能够参考yii\rbac\Item类:

<?php
namespace yii\rbac;

use yii\base\Object;

/**
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Item extends Object
{
    const TYPE_ROLE = 1;
    const TYPE_PERMISSION = 2;

    /**
     * @var integer the type of the item. This should be either [[TYPE_ROLE]] or [[TYPE_PERMISSION]].
     */
    public $type;
    /**
     * @var string the name of the item. This must be globally unique.
     */
    public $name;
    /**
     * @var string the item description
     */
    public $description;
    /**
     * @var string name of the rule associated with this item
     */
    public $ruleName;
    /**
     * @var mixed the additional data associated with this item
     */
    public $data;
    /**
     * @var integer UNIX timestamp representing the item creation time
     */
    public $createdAt;
    /**
     * @var integer UNIX timestamp representing the item updating time
     */
    public $updatedAt;
}

item中的type类型,表示该权限是包含一个权限集合的角色TYPE_ROLE ,仍是单独权限TYPE_PERMISSION。auth_item_child就储存了角色和权限的父子关系数据。

  auth_rule表中定义了规则,auth_item_child储存了用户和角色的关系数据。

 

第三部:建立角色和权限

  这里建立基本的角色author和editArticle权限,以及一个规则,规定只有对本身的文章能够有editArticle权限。在@app目录下新建rbac文件夹:

<?php
namespace app\rbac;

use yii\rbac\Rule;

/**
 * Created by PhpStorm.
 * User: mao
 * Date: 2016/10/28
 * Time: 0:22
 */
class AuthorRule extends Rule
{
    public $name = 'isAuthor';

    public function execute($user, $item, $params)
    {
        return isset($params['post']) ? $params['post'] -> authorId == $user : false;
    }
}

  该规则根据传入的$param数据判断,要修改的文章做者是不是本身。下面进行角色和权限的初始化,新建rbacController控制器,

<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\rbac\AuthorRule;

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

        $rule = new AuthorRule();
        $auth -> add($rule);

        $updateArticle = $auth -> createPermission('updateArticle');
        $updateArticle -> description = '更新本身文章';
        $updateArticle -> ruleName = $rule -> name;
        $auth -> add($updateArticle);

        $author = $auth -> createRole('author');
        $auth -> add($author);
        $auth -> addChild($author, $updateArticle);
    }
}

  访问,http://localhost/?r=rbac/init,后数据库中会生产相应的权限角色数据。

其中,rule中data是被序列化后的对象。

反序列化后以下,

保存了rule的基本信息,权限建立好了,须要给每个注册的用户赋予author权限,具体的注册和发表文章能够本身实现,下面贴一下注册时授予权限的代码:

    public function actionRegister()
    {
        $member = new Member(['scenario' => 'register']);
        $post = Yii::$app -> request -> post();
        if(isset($post['Member']))
        {
            $exist = Member::findIdentityByUsername($post['Member']['username']);
            if(!$exist && $member -> load($post) && $member -> setPassword() && $member -> save())
            {
                $auth = Yii::$app -> authManager;
                $author = $auth -> getRole('author');
                $auth -> assign($author, $member -> id);
                Yii::$app -> user -> login($member);
                return $this -> goHome();
            }
        }

        return $this -> render("register", ['model' => $member]);
    }

用户注册后经过getRole得到角色,而后赋予给用户。下面就是当用户修改文章的时候,根据角色和权限进行判断是否有权限修改。能够经过yii::$app -> user的can方法来进行验证。

    public function actionEdit()
    {
        $articleId = Yii::$app -> request -> get("id");
        $article = Article::findOne(['id' => $articleId]);
        if($article){
            //鉴定是否拥有updateArticle权限
            if(Yii::$app -> user -> can('updateArticle', ['post' => $article])){
                return $this -> render('edit', ['article' => $article]);
            }
            return $this -> render('noAuth');
        }else{
            return $this -> redirect('/?r=article/articles');
        }
    }

其中,第二个参数就是之后会传给AuthorRule中的execute方法的最后一个参数,这里传入的是article的ActiveRecord对象。

当咱们对别人的文章点击编辑后会跳转到你没有权限的提示页面,而本身的文章能够正常修改。

 

 提示没有权限。

参考:

http://www.yiichina.com/doc/guide/2.0/security-authorization

http://en.wikipedia.org/wiki/Role-based_access_control

相关文章
相关标签/搜索