浅析Yii中使用RBAC的完全指南(用户角色权限控制)


Posted in PHP onJune 20, 2013

写在前面
    * 我的feed地址已经修改为: http://feeds.imdong.net ,请更新您的阅读器。
    * 以下内容适合Yii 1.0.x,其他版本可能有略微的差别。
    * 根据您的评论和反馈,本文会不断进行修改和补充,以方便新学习者。

开始准备
Yii提供了强大的配置机制和很多现成的类库。在Yii中使用RBAC是很简单的,完全不需要再写RBAC代码。所以准备工作就是,打开编辑器,跟我来。
设置参数、建立数据库
在配置数组中,增加以下内容:

‘components‘ => array(
    //……
    ‘authManager‘=>array(
            ‘class‘=>‘CDbAuthManager‘,//认证类名称
            ‘defaultRoles‘=>array(‘guest‘),//默认角色
            ‘itemTable‘ => ‘pre_auth_item‘,//认证项表名称
            ‘itemChildTable‘ => ‘pre_auth_item_child‘,//认证项父子关系
            ‘assignmentTable‘ => ‘pre_auth_assignment‘,//认证项赋权关系
        ),
   //……

那这三个数据表怎么建立呢?很简单,去看framework/web/auth/schema.sql。注意要和你的自定义的表名称对应起来。比如SQL文件中的AuthItem你要修改为pre_auth_item。然后在数据库中运行这个SQL文件中的语句。

了解概念
你可能要问,剩下的代码呢?我告诉你,没有啦。RBAC系统就这样建立起来了。但是为了使用它,你需要了解它的运行机制。我会尽量讲的??乱坏恪??ü俜降?BAC文档在这里,但是我曾经看了4-5遍才明白。)

三个概念
你需要了解的是,授权项目可分为operations(行动),tasks(任务)和 roles(角色)。
一个用户拥有一个或者多个角色,比如,我们这里有三个角色:银行行长、银行职员、顾客。我们假设:
    * 张行长 有角色:银行行长、银行职员、顾客(人家自己可以存钱嘛)。
    * 王职员 有角色:银行职员、顾客。
    * 小李 有角色:顾客。

那么,相应的,只要顾客可以做的事情,小李就可以做,王职员和张行长也可以。银行职员可以做的事情,王职员和张行长都可以做,小李就不可以了。

比如,一个“顾客”可以存钱,那么拥有“顾客”角色的张行长、王职员、小李都可以存钱。“银行职员”可以打印顾客的交易记录,那么有“银行职员”角色的张行长和王职员都可以,而小李不行,必须找一个有“银行职员”角色的人才可以打印详细的交易记录。一个“银行行长”才可以进入银行钱库提钱,那么只有张行长可以,因为它才有“银行行长”的角色。
这就是基于角色的认证体系,简称RBAC。

角色的继承
角色是可以继承的,比如我们规定如下:
    * 凡是“银行行长”都是“银行职员”,也就是说,只要银行职员可以做的事情,银行行长都可以做。
    * 凡是“银行职员”都是顾客,同上,顾客可以做的事情银行职员也可以做。
那么角色关系就变成了:
    * 张行长 有角色:银行行长。
    * 王职员 有角色:银行职员。
    * 小李 有角色:顾客。
这样更简单了,这就是角色的继承。

任务的继承
一个任务(task)是可以包含另外一个任务的,我们举个例子,比如“进入银行”。
我们设定“顾客”这个角色有“进入银行”的权限。也就是说,“顾客”可以执行“进入银行”的任务。接下来,我们假设“进入柜台”是进入银行的父权限,也就是说,“进入柜台”包含“进入银行”。只要能“进入柜台”的人都可以“进入银行”。我们把“进入柜台”这个任务权限给“银行职员”。

那么从角色上来说,王职员可以进入银行,因为王职员的角色是“银行职员”,而“银行职员”包含了“顾客”的角色。那么“顾客”可以进行的“任务”对于“银行职员”来说也是可以进行的。而“顾客”可以“进入银行”,那么王职员也可以“进入银行”。这是角色的继承带来的。

我们再假设有个赵领导,是上级领导,可以进入柜台进行视察。那么,我们的任务关系是:
    * 赵领导 有任务:进入柜台。
那么,赵领导就可以“进入银行”。因为“进入银行”是被“进入柜台”包含的任务。只要可以执行“进入柜台”的人都可以执行“进入银行”。这就是任务的继承。

关于行动
行动是不可划分的一级。也就是说。而一个行动是不能包含其他行动的。假设我们有个行动叫“从银行仓库中提钱”。我们把这个行动作包含“进入柜台”。那么只要可以执行“从银行仓库中提钱”的角色都可以执行“进入柜台”这个任务。

三者关系
    * 一个角色可以包含另外一个或者几个角色。
    * 一个角色可以包含另外一个或者几个任务。
    * 一个角色可以包含另外一个或者几个行动。
    *
    * 一个任务可以包含另外一个或者几个任务。
    * 一个任务可以包含另外一个或者几个行动。
    *
    * 一个行动只能被角色或者任务包含,行动是不可以包含其他,也不可再分。
这样,就形成了一个权限管理体系。关于“任务”和“行动”,你不必思考其字面上的意义。这两者就是形成两层权限。

进行赋权
我们建立了RBAC权限管理,就需要进行对权限的WEB管理。这些就需要你自己写代码了。
根据不同种类的项目调用下列方法之一定义授权项目:
    * CAuthManager::createRole
    * CAuthManager::createTask
    * CAuthManager::createOperation
一旦我们拥有一套授权项目,我们可以调用以下方法建立授权项目关系:
    * CAuthManager::addItemChild
    * CAuthManager::removeItemChild
    * CAuthItem::addChild
    * CAuthItem::removeChild
最后,我们调用下列方法来分配角色项目给各个用户:
    * CAuthManager::assign
    * CAuthManager::revoke
下面我们将展示一个例子是关于用所提供的API建立一个授权等级:

$auth=Yii::app()->authManager;
    $auth->createOperation('createPost','create a post');
    $auth->createOperation('readPost','read a post');
    $auth->createOperation('updatePost','update a post');
    $auth->createOperation('deletePost','delete a post');
    $bizRule='return Yii::app()->user->id==$params["post"]->authID;';
    $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);
    $task->addChild('updatePost');
    $role=$auth->createRole('reader');
    $role->addChild('readPost');
    $role=$auth->createRole('author');
    $role->addChild('reader');
    $role->addChild('createPost');
    $role->addChild('updateOwnPost');
    $role=$auth->createRole('editor');
    $role->addChild('reader');
    $role->addChild('updatePost');
    $role=$auth->createRole('admin');
    $role->addChild('editor');
    $role->addChild('author');
    $role->addChild('deletePost');
    $auth->assign('reader','readerA');
    $auth->assign('author','authorB');
    $auth->assign('editor','editorC');
    $auth->assign('admin','adminD');

也就是说,你需要自己写一个管理界面,来列出你的角色、任务、行动,然后可以在这个界面上进行管理。比如增加、删除、修改。

权限检查
假设你在你的管理界面进行了赋权,那么可以在程序里面进行权限检查:

if(  Yii::app()->user->checkAccess('createPost')  )
{
    // 这里可以显示表单等操作
} else {
    // 检查没有通过的可以跳转或者显示警告
}

上面的代码就检查了用户是否可以执行“createPost”,这createPost可能是一个任务,也可以是一个行动。

其他的
对于很多说Yii权限体系RBAC不好用的人其实都没有看懂文档。综合我的体验,我感觉Yii框架的RBAC是我用过的框架里面最好用的。而且是需要自己写代码最少的。
Yii的RBAC有更加高级的用法,比如“业务规则”,“默认角色”。你可以去参考官方文档。
我知道,会有部分人仍旧不理解RBAC,或者不会用Yii的RBAC。没有关系,你可以在下方的评论框里提问。
happy Yii !

PHP 相关文章推荐
SSI指令
Nov 25 PHP
简单的php写入数据库类代码分享
Jul 26 PHP
PHP动态创建Web站点的方法
Aug 14 PHP
php操作mysql数据库的基本类代码
Feb 25 PHP
PHP错误和异长常处理总结
Mar 06 PHP
ThinkPHP模版中导入CSS和JS文件的方法
Nov 29 PHP
PHP整合PayPal支付
Jun 11 PHP
PHP文件与目录操作示例
Dec 24 PHP
PHP实现限制IP访问及提交次数的方法详解
Jul 17 PHP
PHP高精确度运算BC函数库实例详解
Aug 15 PHP
解决php写入数据库乱码的问题
Sep 17 PHP
TP5框架简单登录功能实现方法示例
Oct 31 PHP
php中0,null,empty,空,false,字符串关系的详细介绍
Jun 20 #PHP
解析PHP中数组元素升序、降序以及重新排序的函数
Jun 20 #PHP
解析php中的fopen()函数用打开文件模式说明
Jun 20 #PHP
深入解析PHP内存管理之谁动了我的内存
Jun 20 #PHP
解析php中die(),exit(),return的区别
Jun 20 #PHP
有关PHP性能优化的介绍
Jun 20 #PHP
数组与类使用PHP的可变变量名需要的注意的问题
Jun 20 #PHP
You might like
雄兵连:天使彦天使彦为爱折翼,彦和炙心同时念动的誓言!
2020/03/02 国漫
定制404错误页面,并发信给管理员的程序
2006/10/09 PHP
phpadmin如何导入导出大数据文件及php.ini参数修改
2013/02/18 PHP
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
借助javascript代码判断网页是静态还是伪静态
2014/05/05 Javascript
让浏览器DOM元素最后加载的js方法
2014/07/29 Javascript
深入学习JavaScript中的Rest参数和参数默认值
2015/07/28 Javascript
js实现卡片式项目管理界面UI设计效果
2015/12/08 Javascript
老生常谈遮罩层 滚动条的问题
2016/04/29 Javascript
深入理解React Native原生模块与JS模块通信的几种方式
2017/07/24 Javascript
JS实现继承的几种常用方式示例
2019/06/22 Javascript
解决vue项目中页面调用数据 在数据加载完毕之前出现undefined问题
2019/11/14 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
2019/11/26 Javascript
vue中axios防止多次触发终止多次请求的示例代码(防抖)
2020/02/16 Javascript
vue实现前端分页完整代码
2020/06/17 Javascript
详解JavaScript中分解数字的三种方法
2021/01/05 Javascript
[02:55]2018DOTA2国际邀请赛勇士令状不朽珍藏Ⅲ饰品一览
2018/08/01 DOTA
ptyhon实现sitemap生成示例
2014/03/30 Python
python文件操作之目录遍历实例分析
2015/05/20 Python
Python导入模块时遇到的错误分析
2017/08/30 Python
详解tensorflow载入数据的三种方式
2018/04/24 Python
Pycharm设置去除显示的波浪线方法
2018/10/28 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
2020/05/13 Python
Python抖音快手代码舞(字符舞)的实现方法
2021/02/07 Python
CSS3 mask 遮罩的具体使用方法
2017/11/03 HTML / CSS
美国知名艺术画网站:Art.com
2017/02/09 全球购物
美国在线印刷公司:PsPrint
2017/10/12 全球购物
俄罗斯披萨、寿司和面食送货到家服务:2 Берега
2019/12/15 全球购物
作风整顿剖析材料
2014/09/30 职场文书
机动车登记业务委托书
2014/10/08 职场文书
绍兴鲁迅故居导游词
2015/02/09 职场文书
大学生求职简历自我评价
2015/03/02 职场文书
毕业论文致谢词
2015/05/14 职场文书
MySQL获取所有分类的前N条记录
2021/05/07 MySQL
Pycharm 如何设置HTML文件自动补全代码或标签
2021/05/21 Python
Javascript之datagrid查询详解
2021/09/15 Javascript