如何实现复杂商业应用的权限认证?

Yii的授权体系与我自己写的权限框架差别很大,概念上总有些模糊,希望通过具体案例的解答让我茅塞顿开。

先看一下权限的树型结构图(也可以理解为程序的导航菜单):

要求是这样的,如果用户(或角色)具备"栏目1.1"的权限但不具备其它权限,在导航菜单里只能看到"栏目1.1"所有下级功能及其递归上级,并且递归上级都无法打开:

我的权限框架中有权限继承、权限断开的概念(与NTFS文件系统的权限继承很像):

权限继承:如果用户(或角色)具备"栏目1"的权限,那么"栏目1"下的全部功能都可以看到并能够打开。

权限断开:如果用户(或角色)具备"栏目1"的权限,但禁止了"栏目1.1"的权限,那么栏目1.1下面所有功能都无法看到。

用户和角色的权限关系是交集的。例如"用户1"隶属于"角色1"和"角色2","角色1"具备"栏目1.1"的权限,但"角色2"禁止了"栏目1.1"的"添加"权限,那么"用户1"能够打开"栏目1.1"及其以下全部功能,但看不到它的“添加”功能。

请问Yii是怎样实现如上所述的权限认证呢?

自己顶一下。给个思路就可以。

怎么没有回答的呢?是不是yii的rbac不具备这类功能?

自己的一点理解;

所谓的禁止:在yii的rbac中表现为:没有(没有拥有此角色、任务、操作);

checkAccess()会访问数据库,获得该用户所有(角色,任务,操作),如果多角色,那么他会获得所有角色的权限(角色所拥有的)的叠加,

一旦检查authitem在这个authitems中,则返回true;

A角色拥有XX权限,B角色没有(禁止)XX权限,而该用户拥有A,B角色,此时他是拥有XX权限的;

个人认为这是不是一个误区呢,两个角色同时对某一资源进行访问控制,用户获得两种角色后,对这一资源既有访问,又没有访问权限,这似乎是比较混乱的(至少也应该有个优先级吧,根据权重,判断冲突的资源访问权限依据谁的更重要些;eg: root有adduser权限,member禁止adduser,根据权重可以给用户的adduser分配root的权限)

个人实现的想法;

增加一个字段:明确表明某一authitem是禁止;

重写checkAccess()方法,从检索的authitems中除去明确禁止掉的authiem;

对rbac也没有较深的了解,也许有更好的方法?还请大家指点。

真的很感谢pangjanne这么细心的讲解!了解yii rbac的一些思路了。

我的权限框架可以说非常像文件系统的权限结构,文件系统是树型结构的,权限继承和划分权限时也是树型结构的。

其实咱们两个在这方面的观点诧异是“优先拒绝”还是“优先允许”的问题(当然了yii没有拒绝的概念,只有不赋予权限的概念,所以谈不上优先拒绝)。我不排斥优先允许,这个甚至可以让客户从程序界面上来设置。

如你所说,yii的rbac没有拒绝的概念,所以在商业应用中会比较麻烦。

另外我看过grbac的演示界面,发现yii的权限不是树型结构的,这对商业应用来说可能会比较累。

如果要复写checkAccess或者对底层做什么调整,就不如把之前的权限框架移植到PHP上,我觉得在思想有诧异的情况下改写比重写难度大很多。

不知道我说的对不对,就目前理解来说的,赐教。

就是做个树状的权限管理,挺简单的

就跟普通的树概念一样了,你只要会根据一个tree id,拿到所有子节点,你就可以做了

首先你的树是怎么设计的,这个比较重要,如果可以比较快速(便捷)的获得上下级节点,那么就可以比较方便的判断各个节点的(相对这个用户的权限

其次,定义操作也要根据具体业务情况来具体的看,如果对业务够理解,应该可以定义出比较合理的 Operation 序列

注意建立权限对象的operation时,可以指定 bizRules数据,这个其实是PHP代码啦,应该够灵活了; C??AuthManager::checkAccess 函数可以传递自定义参数给 bizRules

具体就可以你如何理解Yii的RBAC系统了

@Maosong: 你说的权限体系是经典的ACL,它和Yii的RBAC是有区别的。简单来说,ACL有两个要素:操作和操作对象,而RBAC只有一个,那就是操作许可。ACL里的操作对象有可能是很底层的数据对象,对于高层用户而言,这些数据对象可能很难理解。而RBAC的操作许可(permission)可以则不然,在底层它们可以针对很具体的程序操作,而在顶层则可以是对高层用户有意义的操作。从发展形势上看,RBAC更新,有逐渐取代ACL的趋势。

下面是摘录wikipedia的一段话:

RBAC differs from [url="http://en.wikipedia.org/wiki/Access_control_lists"]access control lists/url used in traditional discretionary access control systems in thatit assigns permissions to specific operations with meaning in theorganization, rather than to low level data objects. For example, anaccess control list could be used to grant or deny write access to aparticular system file, but it would not dictate how that file could bechanged. In an RBAC-based system, an operation might be to create a’credit account’ transaction in a financial application or to populatea ‘blood sugar level test’ record in a medical application. Theassignment of permission to perform a particular operation ismeaningful, because the operations are granular with meaning within theapplication. RBAC has been shown to be particularly well suited to [url="http://en.wikipedia.org/wiki/Separation_of_duties"]separation of duties/url requirements, which ensure that two or more people must beinvolved in authorizing critical operations. Necessary and sufficientconditions for safety of SoD in RBAC have been analyzed. An underlyingprinciple of SoD is that no individual should be able to effect abreach of security through dual privilege. By extension, no person mayhold a role that exercises audit, control or review authority overanother, concurrently held role.[sup][/sup][sup][/sup]

大家的回复已经超出了我目前对rbsc的理解,似懂非懂无法作任何回复。但明白了几点,可扩展性、可干预性。另外,如qiang所说,yii的rbsc“在底层它们可以针对很具体的程序操作,而在顶层则可以是对高层用户有意义的操作”,这点很重要,这说明我目前理解的只是rbsc的表层。看来自己要先理解rbsc的核心理念后才能实现我目前的需求。

谢谢大家了。在这里我也说一下自己的权限框架吧,一点经验与大家分享,希望能给出指正。

理解起来比较直观。首先根据需求定义好功能列表,列出树型图,还是以电力行业的一个应用为例:

根据上图为每个节点定义权限ID(与java的命名空间有点相似,灵感也是来源于这里):

定义User、Role及隶属关系:

赋予U1(对于check()函数来说Role和User是一视同仁的,所以我可以直接给)costManage节点的“允许”权限。

赋予R2 costManage.vehicle节点的“禁止”权限。

以上验证规则在数据库中的表现是记录两条授权数据,在用户界面中的表现是点击4下鼠标。

赋予U2 systemManage的“允许”权限:

断开父节点的权限继承实现起来也比较简单,无非是递归到需要断开的节点时跳过即可。

另外用checkChild()判断是否具备某个节点的任何子节点的权限,主要用于导航菜单。