从权限系统谈起,我想只要工作了几年的一般都会对这个有接触,特别是做项目的,^_^,可能很多都自己做过权限系统,一般来说权限系统主要需要做到以下几种情况的控制:
1、身份认证。主要是控制访问系统的用户的身份,以确定用户是否有足够的身份进行操作。
2、系统菜单、按钮的控制。需要根据权限显示相应的菜单和按钮,这种主要是控制显示级别的以及用户正常访问系统操作。
3、系统操作的控制。需要根据权限来控制用户是否有权进行某操作,这个主要是控制避免用户通过不正常的方式来访问系统的操作。(如通过直接敲url等)
4、系统资源级别的控制。这个就比较复杂些,需要控制用户可以看到哪些资源,而资源通常又分成很多种操作级别的资源,如对资源进行管理时看到的就是用户拥有管理权限的资源,如只是对资源进行访问时看到的则为用户拥有访问权限的资源,更为复杂的情况是资源要求支持权限继承的情况,就是对父资源进行授权后,相应的子资源也拥有同样的权限。
对应以上的需求,在权限系统中采用的最多的两种实现方式是RBAC和ACL,无论是RBAC还是ACL,对应以上的需求都是可以实现的,只是实现起来的复杂度不同,还有就是用户操作起来的易用性不同。
上面的需求讲的基本是非常实际的需求,归纳性的和更为合理的描述大家可以看看acegi reference guide里面的描述。
实现权限系统来讲,个人觉得主要是两个方面:
1、授权。主要是授权模型的维护,如资源权限、角色、用户的对应关系等。
2、校验权限。校验权限根据需求主要有校验对于资源进行操作的权限,用户身份的校验,还有一种就是资源操作权限的校验。
在这里主要以RBAC来说说,RBAC规范中RBAC主要分为四个级别,分别为RBAC 0、RBAC 1、RBAC 2和RBAC 3。
RBAC 0又称为Core RBAC,实现的为基本的权限模型,如用户与角色、角色与资源权限、资源权限与资源、资源操作的关系的维护,同时提供基于角色的资源操作权限的校验,类似的伪代码:role.doPrivilege(Principle,Resource,Operation),相对来讲RBAC 0是比较容易实现的,在RBAC 0中进行权限校验时的关键就是根据用户的角色来检验用户是否有操作的权限。
RBAC 1中提出了角色权限继承的实现,虽然看起来只是增加了一个角色权限继承,但在实现起来系统的复杂度则是大大的增加了,在RBAC 0中校验一个用户是否拥有对某资源的操作权限时只需校验用户的角色即可,现在则变成了除了需要校验用户的角色权限外,在用户角色权限不足的情况下还需校验其父角色的权限,这个在系统效率方面必然会造成影响,但其实对于资源操作来讲还算是比较好处理的,因为毕竟可以通过缓存等等技术来解决,但对于系统资源级别的权限控制来说则变得更为复杂多了,因为在进行系统资源级别权限控制时通常需要分页的获取有权限的资源,而通常分页我们需要依赖数据库进行实现,也就是说并不是直接获取所有的资源然后再进行分页,这样在进行大量资源访问的时候是会出现问题的,这个时候问题就很明显的出现了,因为通过RBAC模型的话我们只能做到先获取出所有的资源,然后进行权限过滤,而且这个时候在进行权限过滤的时候会比较的麻烦,需要去校验用户的角色以及父角色,不断的判断,这个时候其实ACL的优点倒是体现了,因为按照ACL的话是可以直接获取出用户有权限访问的资源的,这样的话分页其实同样不是问题了,但ACL的麻烦同样也在继承这个地方,这样的话授权模型会非常复杂,因为在授权的时候需要维护好ACL这张表,把用户所在的角色的父角色的权限也要考虑进来,同时维护ACL的表,而且在角色变动的时候也要去维护ACL表,可以看出这其实也是很复杂的,就举一个简单的例子,如果一个父角色下有几十个子角色,那么在父角色对于资源访问的权限变动时那么所有的子角色的资源都需变动,这个时候ACL表就得变动。
RBAC 2则更为复杂,RBAC 2中提出了角色权限互斥的问题,其实在角色权限继承的基础上我们就会考虑到这个问题,既然角色权限继承那么很容易出现权限互斥的问题,RBAC 2模型就是为了解决这个。
RBAC 3则没什么说的,因为它就是RBAC 1和RBAC 2都实现。
上面讲的是没什么章理去了,呵呵,不好意思,其实不管采用什么模型,对用户而言重要的是授权的简易性和校验权限的高效性,当然,还有就是权限控制的有效性,而RBAC模型和ACL模型都是为了这个目标而去,其实通过上面的大概介绍可以看出,RBAC模型在授权模型上会比较的简单和清晰,而ACL模型则在校验权限上比较的简单和高效,所以说两者各有优缺点,如果有什么能两者都实现的就好了,因为两者的优点其实也是非常的映射出两者的缺点。
其实在没有权限继承的时候权限系统的时候是比较容易的,但为了提高系统管理的方便,权限继承也是不可避免的会出现,这个时候就要考虑在什么时候去完成权限继承,是授权时完成还是校验权限时完成,授权时完成就会造成授权模型的复杂,但可以保证校验权限时的简便,校验权限时完成则可保证授权时的简单,但造成校验权限时的低效。
最后针对以上需求来说,还是认为1、2、3点需求是比较容易做到的,即使在权限继承的情况下也不是那么的难,但对于需求4来说目前仍然没有想出很好的办法,目前的做法只能是ACL,也就是增加授权时的复杂,但保证校验权限时的简单。
这篇作为漫谈权限系统的开篇,讲的可能有些混乱了,在第二篇中将重点来描述RBAC和ACL分别实现需求1、2、3的方法。