浅析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 相关文章推荐
一个PHP操作Access类(PHP+ODBC+Access)
Jan 02 PHP
PHP4中session登录页面的应用
Jul 25 PHP
PHP统计二维数组元素个数的方法
Nov 12 PHP
Discuz批量替换帖子内容的方法(使用SQL更新数据库)
Jun 23 PHP
PHP获取一段文本显示点阵宽度和高度的方法
Mar 12 PHP
PHP新建类问题分析及解决思路
Nov 19 PHP
利用switch语句进行多选一判断的实例代码
Nov 14 PHP
PHP中大括号'{}'用法实例总结
Feb 08 PHP
PHP定义字符串的四种方式详解
Feb 06 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
Apr 23 PHP
laravel dingo API返回自定义错误信息的实例
Sep 29 PHP
laravel model模型定义实现开启自动管理时间created_at,updated_at
Oct 17 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
Apache, PHP在Windows 9x/NT下的安装与配置 (一)
2006/10/09 PHP
PHP中for与foreach的区别分析
2011/03/09 PHP
php中get_object_vars()方法用法实例
2015/02/08 PHP
JavaScript instanceof 的使用方法示例介绍
2013/10/23 Javascript
jquery实现弹出窗口效果的实例代码
2013/11/28 Javascript
中止javascript执行的方法
2014/02/14 Javascript
使用js检测浏览器是否支持html5中的video标签的方法
2014/03/12 Javascript
使用cluster 将自己的Node服务器扩展为多线程服务器
2014/11/10 Javascript
javascript中的五种基本数据类型
2015/08/26 Javascript
用户代理字符串userAgent可实现的四个识别
2015/09/20 Javascript
javascript动态添加checkbox复选框的方法
2015/12/23 Javascript
html5+javascript实现简单上传的注意细节
2016/04/18 Javascript
JavaScript 对象详细整理总结
2016/09/29 Javascript
原生JS实现几个常用DOM操作API实例
2017/01/19 Javascript
如何使用JS在HTML中自定义字符串格式化
2017/07/20 Javascript
详解Vue.js组件可复用性的混合(mixin)方式和自定义指令
2017/09/06 Javascript
浅谈webpack 自动刷新与解析
2018/04/09 Javascript
ios设备中angularjs无法改变页面title的解决方法
2018/09/13 Javascript
解决在layer.open中使用时间控件laydate失败的问题
2019/09/11 Javascript
[44:40]2018DOTA2亚洲邀请赛3月30日 小组赛A组Liquid VS OG
2018/03/31 DOTA
使用python编写批量卸载手机中安装的android应用脚本
2014/07/21 Python
数据清洗--DataFrame中的空值处理方法
2018/07/03 Python
Windows上安装tensorflow  详细教程(图文详解)
2020/02/04 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
HTML5 Canvas基本线条绘制的实例教程
2016/03/17 HTML / CSS
美国求婚钻戒网站:Super Jeweler
2016/08/27 全球购物
全球立体声:World Wide Stereo
2018/09/29 全球购物
模范教师事迹材料
2014/02/10 职场文书
百年校庆节目主持词
2014/03/27 职场文书
争做文明公民倡议书
2014/08/29 职场文书
业务员工作态度散漫检讨书
2014/11/02 职场文书
同学会邀请函模板
2015/01/30 职场文书
道歉情书大全
2015/05/12 职场文书
ROS系统将python包编译为可执行文件的简单步骤
2021/07/25 Python
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python
python APScheduler执行定时任务介绍
2022/04/19 Python