基于Web的权限管理框架之功能规格

来源:互联网 发布:阿里云网站免费模板 编辑:程序博客网 时间:2024/04/30 13:06
 

基于Web的权限管理框架功能规格说明书

研究开发中心 邵正军

修订历史纪录:

2005-11-14 邵正军 1.0 初建

名词解释:

Web应用程序:Web Application,又简称Web应用、Web-App

最终用户:最终使用Web应用程序的用户,包括系统管理员、普通用户。

CSSHTML页面上用它来控制显示样式,以达到样式和内容分离的效果。

1       前言

本产品是个权限管理框架,为Web应用程序的权限管理提供基础设施和框架。

任凭人们发挥怎样的想象力,目前这份规格说明书都不是完整的,所有措辞都需要经过多次修订才能最后定稿。

本说明书描述的是完全从用户(是指本框架的用户,包括Web-App开发者、最终用户)的视角看产品如何工作的内容。它不关心产品内部如何实现,它谈论的是功能特性。在这里给出屏幕图形与布局仅仅是为了演示背后蕴含的功能性,实际的外观与感觉(look and feel)将根据图形设计人员的输入与用户反馈随时间不断加以改进。

2       背景

你是否有过需要为一个应用程序创建登录验证和授权机制的经历呢?如果你是一个比较有经验的程序员,那你一定有过,而且可能不止一次了。那么,再回想看看,是不是会感觉每一次的新实现都好像似曾相识、可是又与以前不完全一样?唔,这正是我们要思考的地方,为什么我们要一再地重复自己?

3       目标

我们的目标是产出一个基于Web的通用权限管理框架(以下简称权限框架/框架),供Browser/Server结构的Web应用程序(以下简称Web应用/Web-App)使用,免去每个项目重复从头开发权限管理功能的痛苦,提高生产力。

4       范围界定

权限框架用Java语言实现。如果你想在J2EE多层结构中寻找它的位置,那你到Web层去找就对了,它的定位就在Web层。

它需要运行在Servlet2.3/JSP1.2or later)规范兼容的Web server(譬如Tomcat4.1.x or later)中,为Web-App的权限管理提供基础设施和框架。

本框架立足于满足大部分情况下粗粒度权限控制的需要,譬如系统功能(菜单、按钮等)的访问控制。对常见通用权限管理行为(譬如用户/角色信息维护、菜单/按钮的访问权限许可等)提供必要的缺省实现,也提供途径给Web应用开发者覆盖这些缺省实现;

对于细粒度的权限控制,譬如种种业务层面上的权限管理要求,由于权限框架无法预知也不能做任何假定,所以这也是框架实现难点所在。本框架的解决方案是以API的形式提供扩展点,Web应用开发者在扩展点上插入满足自己业务规则要求的权限许可模块即可。由于外部扩展也是建立在权限框架的游戏规则上的,所以就保证了整个Web应用的权限管理都是在协调一致的机制下进行。

5       权限模型

解决复杂的权限管理问题的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。这里涉及的相关概念说明如下:

l         Who权限的拥有者或主体。典型的有PrincipalUserGroupRoleActor等等。本框架的访问控制方法会采用“基于角色的访问控制(主,公认的有效方法) + 针对个别用户的访问控制(辅,增加灵活性) + 用户组”(这一点参见[访问控制方法的考虑]一节),所以直接跟授权有关系的实体就只有角色(Role)和用户(User)。譬如:业务经理(Role),张三(User

l         What权限针对的资源(Resource)(包括资源类别(the type of Resource)和资源实例(the instance of Resource))。譬如:报表。

l         How亦作action,表示某种访问方法(亦请参考Operator条目解释)。譬如:删除。

l         Operator操作。表示施加于WhatHow动作。是一种Resource Related的概念,单独的How动作是没有实际意义的,譬如:删除;只有与具体资源结合在一起才有意义,譬如:删除报表。

 

访问控制方法的考虑:

5.1    基于角色的访问控制

基于角色的访问控制(RBAC)是目前公认的解决企业级的统一资源访问控制的有效方法。其显著的两大特征是:

1. 减小授权管理的复杂性,降低管理开销。

2. 灵活地支持企业的安全策略,并对企业的变化有很大的伸缩性。

概念示意图:

说明:

这种方法中,角色(Role)权限分配的单位与载体。权限不考虑分配给特定的用户。相对于基于用户(User)的访问控制来讲,角色的数量比用户总是少得多,因此极大地降低了系统管理员授权管理的复杂性。同时一个用户可以身兼多个角色,给安全策略带来了很大的灵活性和伸缩性。

对一个具体用户来讲,他拥有的权限是:对该用户身兼的角色(可能是多个)授予的权限的并集(Union)。

这可以解决90%的问题。但是,现实当中有一些比较特殊的情况,需要在角色的基础上再针对某个具体的用户指定特别的访问资源限制,这时就无法优雅地解决了。

5.2    基于角色的访问控制 + 针对个别用户的访问控制

这种方法立足于要解决上一种方法剩下的那10%的问题。让系统管理员也可以针对某个具体用户指定权限,支持对角色授权同时对用户授权的情况。

概念示意图:

说明:

对一个具体用户来讲,他拥有的权限是:直接对该用户本身授予的权限对该用户身兼的角色(可能是多个)授予的权限的并集(Union)。

从上图中箭头线的粗细可以看出,虽然权限框架同时支持两种方式及其结合,但还是希望有个[主要/辅助]之分:针对角色的授权是公认的好方法,应为主;针对用户的授权用来配合解决特定情况下的需要,应为辅。这些道理要让系统管理员明白,最好能在系统授权界面上有所体现、有所提醒。

这种方法看起来很不错!唔,让我们再想想有无其他的需要……对了,古语云:物以类聚,人以群分。现实中的人们生活生产总是分成一组一组的,以组为单位分配事务似乎已成了现实中人的思维习惯,而我们的权限模型在这方面似乎还欠缺点什么……

5.3    基于角色的访问控制 + 针对个别用户的访问控制 + 用户组

这种方法立足于要弥补上一种方法留下的那个欠缺,引入“用户组(Group)的概念”。

概念示意图:

说明:

这种方法是完全建立在上一种方法之上的,与上一种方法不同点在于增加了用户组。人们可以按照现实中的思维习惯,将用户编成组,再将用户组与角色关联。当然用户仍然可以直接与角色关联。

对一个具体用户来讲,他拥有的权限是:直接对该用户本身授予的权限对该用户身兼的角色(可能是多个)授予的权限对该用户所属的组(可能是多个)授予的权限的并集(Union)。

所以,比对以上多种访问控制方法,我们判定,胜出者是:“基于角色的访问控制 + 针对个别用户的访问控制 + 用户组”,这将是我们的权限框架的权限模型所采用的访问控制方法。

6       从系统边界看到的与本框架相关者

说明:

建立在本框架基础上的Web-App系统的权限子系统核心会涉及以下几个部分:

1)         在框架基础上的业务相关扩展(如果有的话)。参与者为Web-App开发者,在系统开发时进行。

2)         定义权限。参与者为Web-App开发者,设计和实现系统时便需划分:整个系统所有子系统或模块中,应该有哪些受控资源及其访问权限。这里完成的是PrivilegeResource的声明,并没有真正将Privilege与具体Resource实例联系在一起形成Operator(这里的相关概念参见“权限模型”一节)。

3)         分配权限。参与者为Web-App这个系统的最终用户中的系统管理员(admin)角色。系统管理员指定PrivilegeResource Instance的关联。在这一步,权限真正与资源实例联系到了一起,产生了Operator。系统管理员利用Operator这个基本元素,来创造他想要的权限体系((这里的相关概念参见“权限模型”一节))。如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联,为不同角色分配相应权限等等,这些操作都是由系统管理员来完成的。

4)         使用权限。参与者为Web-App这个系统的最终用户中的普通用户(User)。他们使用系统管理员分配给的权限去访问各个定义好的受控资源。

下文中在描述框架的功能规格时,会因时因景从不同的相关参与者的角度来阐述看法和要求,为便于醒目地识别,届时会以“[<相关参与者>相关:]”的形式(譬如:“[Web-App开发人员相关:]”)来表示,请读者注意此约定。

7       最终用户直接体验的功能

此部分功能的用户是最终用户。

从上层Web-App系统菜单的角度来看,权限系统提供的功能就表现为两个入口点(URL):1)权限管理;2)变更密码。前者面向系统管理员角色,属于受控资源;后者面向所有用户,属于不受控资源。下面分别详述。

7.1    权限管理系列功能

这些功能维护着系统的安全保护机制,均涉及敏感信息,关系着权限子系统能否正常工作,所以这些功能本身均应该有安全保护机制,而且这种保护机制应该是内建于框架内的,不应该依赖于上层Web应用(有趣,这容易让人想起那个古老的鸡与蛋的故事)。

这些功能应只有admin角色才有权使用,被赋予系统管理员角色的所有用户皆可访问这些资源(功能)。任何角色和用户均无法剥夺系统管理员的这些权利。这些功能包括:角色信息维护,用户组信息维护,用户信息维护,给用户组分配用户,将用户组与角色关联,为不同角色分配相应权限等等。这些功能汇集为一个入口点,一般通过上层Web-App的系统菜单进入(可能的菜单项名字是“权限管理”)。

入口引出的页面长相大致如下:

页面分左右两帧,左帧为树形结构导航,所有的页面都将展示在右帧显示区。

[Web-App开发人员相关:] 哦,老兄,你的这些页面长成什么样?我的Web-App是经过美工专门设计的,有鲜明的主题,我可不想权限子系统看起来与我的产品格格不入!

本产品定位为权限框架,将来必为许许多多显示风格各异的Web-App所用,那么怎样才能使本框架的页面自然融入到这些Web-App中呢?答案是使用CSS。框架的所有页面,其显示样式全部通过一个统一的CSS文件来控制,Web-App开发者将来只要把这个CSS文件替换成与相应Web-App匹配的风格即可,无需改动任何页面代码。

7.1.1   用户(User)信息管理维护

“用户列表”界面长相大致如下:

说明:

点击用户名超链接和“新建”按钮会分别转至编辑和新建界面,这两个画面长相很类似,“编辑用户”界面大致如下:

说明:

你已看到,本框架支持针对个别用户的授权。但正如前文“基于角色的访问控制 + 针对个别用户的访问控制”一节所述:针对角色的授权是公认的好方法,应为主;针对用户的授权用来配合解决特定情况下的需要,应为辅。所以此处在“授权”按钮旁边给出了相应的文字警示以提醒系统管理员。点击“授权”按钮,弹出用户授权界面,其长相请参见“角色授权界面”。

用户密码是非常重要的信息,需要有相应的传输保密机制。

[Web-App开发人员相关:] 观察力敏锐的Web-App开发人员已经看出一些问题来了,有的已经迫不及待地发问:嘿,我说,这些信息你们存放在哪儿?在引入你们这一套权限框架之前我们系统已经有了一些用户权限管理方面的数据库表,可是你们不至于要让我的系统有两套这样存储着相同意义的数据却结构相异毫不相干的数据库表吧?那会徒生无尽烦恼并会彻底把用户弄糊涂!那决不行!

嗯,问得棒极了!我们的解答是这样:正如你透过界面所看到的(真厉害),权限框架有一套用户权限管理方面的数据库表,表结构基于我们的权限模型(前文有述)。权限框架的产品包里会缺省提供主流数据库的建表脚本(MySQLOracleSybaseSQL-Server)。但在我们看来,Web-App开发者根本无需了解这些表的结构甚至于存在,因为你既然引入了权限框架,干嘛还要陷身于这些苦累的活呢,全部交给权限框架去处理吧!

有一种情况例外,就是上文提问中讲到的“在引入你们这一套权限框架之前我们系统已经有了一些用户权限管理方面的数据库表”,并且可能有许多程序在用这些表,为了引入权限框架而去改这些程序,Web-App程序员才不愿意干呢(重要的是这些程序并没有犯错)。我们这样解决这个问题:框架可以不用自带的数据库表而用Web-App既有的。表名是什么,字段名是什么,这些都不重要,权限框架把这些做成灵活的可配置项;重要的是我们必须就这些表的结构和含义达成一致,这是协议,不满足这个协议,那你的数据库表就必须改(增),你的相关程序就必须改!

协议如下

用户表:用户名(字符型,PK),密码(字符型),用户全名(字符型)

用户-用户组映射表:组名(字符型,PK),用户名(字符型,PK

用户组表:组名(字符型,PK),描述(字符型)

角色-用户组映射表:角色名(字符型,PK),用户组名(字符型,PK

角色表:角色名(字符型,PK),描述(字符型)

角色-用户映射表:角色名(字符型,PK),用户名(字符型,PK

7.1.2   用户组(Group)信息管理维护

“用户组列表”界面长相与“用户列表”大致相同,但是在“删除”的处理策略上是这样的:只有空的用户组(即没有关联到任何用户)才能够删除,否则不予执行删除动作并且给用户以友好的警示信息。

点击用户组名超链接和“新建”按钮会分别转至编辑和新建界面,这两个画面长相很类似,“编辑用户组”界面大致如下:

7.1.3   角色(Role)信息管理维护

“角色列表”界面长相与“用户列表”大致相同,但是在“删除”的处理策略上是这样的:只有满足以下条件才能删除角色,1)没有与任何用户组关联;2)没有与任何用户关联;3)没有与任何授权操作关联。除此以外不予执行删除动作并且给用户以友好的警示信息。

点击“角色列表”界面的“新建”按钮会转至“新建”界面,大致长相如下:

说明:

从现实情况总结来看,系统管理员授权管理的开销有时还是蛮大的,很多情况下从相近的已经授权的角色复制权限然后改一改要比全新从头授权要轻松得多。所以,本框架加入“从已有角色复制权限”这一功能纯粹是为了便于系统管理员工作。用户填写完毕点击“Save”,处理完毕后即会转向角色列表界面。

点击“角色列表”界面的角色名超链接会转至“编辑”界面,这与“新建”画面长相很类似,“编辑角色”界面大致如下:

说明:

点击“授权...”时会出现角色授权界面,其长相大致如下:

“增加”的界面大致如下:

<暂缺>

需要关注一点:系统管理员在对角色进行权限许可授予时,往往是工作量巨大而且特别乏味。所以一定要注意尽量降低管理员管理开销。

关于这一点,请看一个典型的场景:某个系统中有一些公共的菜单需要开放给系统的每一个用户,譬如:“修改密码”、“关于...”、“系统帮助”等等(朋友,数一下吧,是不是几乎每个系统都有这种类似的情况?),对系统管理员来说,这无疑是一种挥之不去的负担,他/她必须为每个用户都指定一遍这些公用菜单的访问权限...

这显然不是我们希望看到的情景,我们必须为系统管理员减负!解决方法是单独设置一个不受访问权限控制的“非受控资源/公共菜单按钮”登记区,凡在此登记的菜单按钮都权限框架都认为其可为所有用户访问。

“编辑”的界面大致如下:

<暂缺>

7.2    变更密码功能

这个功能是提供给LoginWeb-App系统中的每个用户(包括系统管理员和普通用户)的,该资源应属于不受控资源,不在权限管理的授权范围,人人可访问。权限框架在提供这个功能的同时亦应有机制保证这一点。进一步说,系统投入运行后,新增加一个角色/用户,即便在没有接受系统管理员任何授权时缺省都是可访问这个功能的。Web-App开发者亦需要明白这个道理并适当安排菜单入口(可能的菜单项名字是“变更密码”)。

这个功能的页面长相大致如下:

8       登录(Login)认证功能

原则:可插入(pluggable)性,低侵入性。

设想一个场景:一个Web-App系统从初期的Demo原形(prototype)逐步演化而来,到最后,功能基本完备了,是要考虑用户登录认证这一块功能的时候了。这时引入本权限框架,开发人员不需要改动Web-App任何既有代码,甚至于可以完全不晓得此登录认证功能的存在,即可享用框架带来的登录认证功能,完全是一种通过run-time配置即可插入使用的机制。这就是我们想要提供的登录认证功能。

 [技术实现相关:] 或许会考虑使用Servlet specification 2.3Filter机制来实现。这种情况,Web-App开发人员只需把框架提供的拦截器通过Web-App部署描述文件配置好即可,它会拦截所有的Http-Request,若该用户已经是合法登录用户则放行,否则转向Login页面。为了方便上层Web-App,该页面由权限框架提供缺省实现,无需Web-App编码实现。如果要求与相应Web-App的显示风格匹配,只要替换CSS文件即可。若CSS还无法满足要求,则可直接替换掉该页面文件,但这时有一点要求:用户名域、密码域的元素名称以及FormMethodAction取值都必须与原文件相同。Login页面的Formaction指向的target必须是权限框架提供,因为这涉及到认证的动作以及下一步的对所请求资源的授权验证。

再设想一个场景: Web-App系统已经投入使用,有一个用户的职责就是每天察看某一张报表的数据。可是要看到这张报表他必须:每次登录然后等待出现系统主界面,然后层层深入到第三层菜单,点击其中的一个菜单项,出现相应的画面,在此画面上点击某个超级链接,才能看到这张报表。很繁琐!但这个用户是个聪明人,他把这个超级链接放到浏览器的“我的最爱”或者“收藏夹”中,期望每次点击此链接,系统登录后便直接转到这个请求的链接,他就可以看到报表了(我仅仅是看指定的报表而已,为什么需要每次看到主界面和讨厌的三层菜单?)。

上段描述的场景很典型,也合情合理。但并不是所有的应用都有这种情况,有的系统就要求不管你请求的是什么资源,每次都必须把你带到主界面。

那么权限框架如何处理这两种不同的情况?支持其中的哪一种?解答是:两种都支持,做成灵活的配置项,根据具体Web-App项目要求,通过run-time配置即可。

[Web-App开发人员相关:] 关于用户名/密码等信息的存储约定,请参见“数据表协议”。

9       访问控制(Access control)功能

此部分功能的用户是Web-App开发人员。

正如权限模型一节所说,解决复杂的权限管理问题的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。当然,判定当前登录用户是谁(那个用户,什么角色等),那是权限框架的事情,所以Web-App开发人员在程序中只需向权限框架提问:“可以对What进行How的访问操作吗?”。这就够了,这就是权限框架要提供给上层Web-AppAPI

大家要知道,一个系统在设计阶段便需划分:整个系统应该有多少子系统、多少子模块、多少菜单、多少页面按钮,其中有哪些应该是受控资源,它的访问权限是怎样的。这是权限定义,完成的是PrivilegeHow)与ResourceWhat)的声明。直到系统管理员进行了权限分配时,权限才真正与资源实例联系到了一起,注册于某个地方(也许是数据库,也许是文件)。程序执行到向权限框架提问:“可以对What进行How的访问操作吗?”时,框架会到权限注册处去匹配寻找,便可以做出该用户是否有权访问该资源的判定。

基本上,访问控制可以有两个控制级别:

l         粗粒度:表示类别(Type)级,即仅考虑对象的类别(the type of object),不考虑对象的某个特定实例。比如,查询/报表管理中,创建、删除,对所有的用户都一视同仁,并不区分操作的具体对象实例。

l         细粒度:表示实例(Instance)级,即需要考虑具体对象的实例(the instance of object),当然,细粒度是在考虑粗粒度的对象类别之后才再考虑特定实例。比如,查询/报表管理中,删除某报表,需要区分该报表实例是否为当前用户所创建。

下面分别从这两个方面介绍本框架的支持情况:

9.1    系统功能项权限控制(粗粒度权限控制)

这种控制是系统最常见的需求,不同用户对系统功能项有不同的限制,通常表现为某些系统菜单、页面按钮的不可见或灰掉。在这一控制层面,权限框架提供直接完全支持。

[Web-App开发人员相关:] 必须预先对全系统的受控以及非受控的功能项(菜单、按钮)作一个全局规划,保证每一个功能项分配有一个全局唯一的标识号,并向权限框架注册。然后只要在需要决定是否显示某个菜单、按钮之前,调用权限框架API向权限框架提类似问题:“可以对new MenuPermession(“a.b.c”)进行访问操作吗?”即可,根据结果的Ture/False决定是否显示这个菜单、按钮。

9.2    防止直接URL侵入

因为是Web应用程序的缘故,浏览器不受Web-App或权限框架控制,所以单纯采用上一节的介绍的方法会导致安全隐患。

请看一个场景:因为权限不允许,用户张三的菜单“报表”被封掉了,在系统给他展现出来的界面中根本看不到这个菜单,于是他根本无法访问“报表”,OK,权限系统赢了!可是,有一天张三上厕所的时候无意中看到李四在使用“报表”菜单,这小子打了鬼主意,乘李四离开座位的时候偷偷到他机器上,点击该菜单并记下其URL,然后回到自己机器前,在浏览器的地址栏敲入这个URL,哇,“报表”界面出现了!瞧,这一下,权限系统输了,输得很惨!

所以,可以看到,这种“直接URL侵入”的问题是非常危险的,特别是在Web应用中你根本无法阻止用户在地址栏输入任何东西。

权限框架必须负责解决这个问题,这也是他的职责所在!怎么解决?哦,有一种简单的解决方法如下:[Web-App开发人员相关:] 除了保证每一个功能项(菜单、按钮)分配有一个全局唯一的标识号外,每一个功能项还必须分配有一个全局唯一的Http-Request URL并向权限框架注册。这样的话,被限制访问的功能项,首先不会显示出来,其次就算用户在地址栏直接输入URL,也会被权限框架的拦截器拦截然后判定为非法,然后阻拦掉。于是系统就是安全的了!

9.3    业务面上的定制权限控制(细粒度权限控制)

系统功能项权限控制可以解决菜单按钮是否可见的问题,譬如:所有RD研发员角色都可以看见报表列表界面的“删除”按钮、可以执行这个动作,而其他角色则不可以。这种方法确实可以解决类别(Type)级的粗粒度权限控制问题。

但是它解决不了这样的实例(Instance)级的细粒度业务规则级别的问题,譬如:虽然所有RD研发员角色都可以看见报表列表界面的“删除”按钮、可以执行这个动作,但是只有选中的该报表是当前用户所创建才可以真正允许删除。

正如前文“范围界定”一节所说,对于类似于这种,各种各样业务层面上的权限管理要求,由于权限框架无法预知也不能做任何假定,所以这也是框架实现难点所在。本框架的解决方案是以API的形式提供扩展点,Web应用开发者在扩展点上插入满足自己业务规则要求的权限许可模块即可。由于外部扩展也是建立在权限框架的游戏规则上的,所以就保证了整个Web应用的权限管理都是在协调一致的机制下进行。