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

相關文章
相關標籤/搜索