1 概述
几乎所有的项目都会涉及到权限控制的问题。在很多时候,设计者往往根据具体的需求来做权限控制而不理会通用性,但这样的设计往往造成一个项目一种模式,给日后的维护和升级扩展带来难度。
对于一个软件产品,其初级版本往往是简单的,因此权限管理也会相对简单,但随着不断的升级,功能的增加使业务模型变得越来越复杂,设计者就会发现原来的权限控制机制过于简陋了或者缺乏弹性了。这个时候再调整往往意味着要修改大量的历史代码并重新进行测试,这无疑是痛苦和让人印象深刻的。
因此,在项目设计的初期我们就需要为此作好充分的准备,这个准备包括两个方面:
l 选择一个正确的权限管理模型
l 建立一个独立的和业务代码无关的易于扩展的权限管理机制
2 RBAC权限管理模型
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用 户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。
RBAC 模型作为目前最为广泛接受的权限模型。 NIST (The National Institute of Standards and Technology,美国国家标准与技术研究院)标准RBAC模型由4个部件模型组成,这4个部件模型分别是基本模型RBAC0(Core RBAC)、角色分级模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和统一模型RBAC3(Combines RBAC)[1]。RBAC0模型如图1所示。
与另一种常用的权限管理模型ACL比较,RBAC模型对权限控制的颗粒度更细,更容易扩展和富有弹性。
3 基于RBAC0的数据库模型设计
3.1 基本的数据库模型
![JSF项目中实现基于RBAC模型的权限管理设计(一) - laomaowww - laomaowww的博客](http://img0.ph.126.net/c-JpPG1-7sjE_cwjb0KFgA==/1089308159887528080.jpg)
这个模型用五张表来描述权限管理的模型。适用于角色和资源并不是太多的情况。
3.2 对资源分组后的数据库模型
![JSF项目中实现基于RBAC模型的权限管理设计(一) - laomaowww - laomaowww的博客](http://img2.ph.126.net/hVtfQWsRro4RDHG-4Lpgyg==/2585347661104870702.jpg)
对于复杂的系统,角色众多,资源众多,给角色分配资源的工作就比较繁重,授权的管理页面篇幅就会比较大。因此,这个模型增加了Permission表,用于给资源进行分组(分配)处理后再给映射到角色。
4 JSF中的RBAC的实现
4.1 资源分类和管理
4.1.1 资源分类
对于WEB项目,权限管理的资源基本上可以分为两种类型,一种是文件、目录类型,比如页面文件、多媒体文件等,以及目录。这一类型的资源往往表现为一种路径的形式,我们称这种类型的资源为URL类型。
另一种是页面上的菜单、按钮等具体操作资源,笔者将这种类型称为ACTION类型。
4.1.2 资源管理和初始化
对于一个信息管理型的项目来说,需要鉴权的资源是非常多的,因此对资源的管理也是后台管理的一个重要的组成部分。但我们的难题是这些资源在项目部署的时候如何轻松地导入到数据库中去呢。写SQL脚本,或者让后台管理员一条一条输入?
对于软件的使用者或者维护者来说,这样的方式都是一场噩梦。所以,作为软件开发者,必须为用户考虑到这一点。明智的做法是:预先定义好绝大部分的资源,写成xml形式的文件,在系统部署的时候导入到数据库中。而后台的资源管理模块(页面)仅仅把它当作一个查漏补缺的功能吧。
很多WEB项目往往会做一个install页面,这个页面要求用户输入一个超级管理员账号和信息。在用户提交时在后台完成数据库建库、初始化数据(给某些需要的表插入预定义记录)和其它一些初始化配置的工作。这是一个很好的习惯,我们对资源的初始化也可以在Install中完成,包括预定义的角色、以及预定义角色的资源分配。
4.2 鉴权服务模块
根据用户、角色、资源这个三者的关系,设计一个鉴权服务类以供调用是一个明智的想法。
具体的代码就不在此罗列了。
4.3 权限验证模块设计
一个好的权限管理机制在项目中应用时,最好不要让程序员在具体业务代码的方法中来判断用户权限。因为这意味着大量重复的代码。同时,也会导致权限机制的修改造成所有业务代码都需要修改一遍。
最好办法是实现与具体业务代码无关的独立的权限验证模块。这个模块可以拦截用户对资源的访问请求,并且在该请求被实施前做出权限判断,将权限不符的访问导向警告或提示页面。
在普通的JSP项目中,我们往往会利用Tomcat的Servlet filter机制来实现这样的功能,但filter机制的颗粒度不够,无法做到ACTION级别。另一个问题是,在JSF项目中,页面的跳转默认使用的是Forward形式,而不是redirect形式的URL重定向,因此Filter往往无法截获页面的转向。
因此,在JSF项目中我们首先需要解决如何截获到用户对资源的访问的问题。