本站首页    管理页面    写新日志    退出


«December 2025»
123456
78910111213
14151617181920
21222324252627
28293031


公告
本博客在此声明所有文章均为转摘,只做资料收集使用。并无其他商业用途。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:210
评论数量:205
留言数量:-19
访问次数:929359
建立时间:2007年5月10日




[系统设计]权限系统概要
文章收藏,  网上资源,  软件技术,  电脑与网络

李小白 发表于 2007/7/26 10:20:59

前言:权限往往是一个极其复杂的问题,但也可简单表述为这样的逻辑表达式:判断“Who对What(Which)进行How的操作”的逻辑表达式是否为真。针对不同的应用,需要根据项目的实际情况和具体架构,在维护性、灵活性、完整性等N多个方案之间比较权衡,选择符合的方案。目标:直观,因为系统最终会由最终用户来维护,权限分配的直观和容易理解,显得比较重要,系统不辞劳苦的实现了组的继承,除了功能的必须,更主要的就是因为它足够直观。简单,包括概念数量上的简单和意义上的简单还有功能上的简单。想用一个权限系统解决所有的权限问题是不现实的。设计中将常常变化的“定制”特点比较强的部分判断为业务逻辑,而将常常相同的“通用”特点比较强的部分判断为权限逻辑就是基于这样的思路。扩展,采用可继承在扩展上的困难。的Group概念在支持权限以组方式定义的同时有效避免了重定义时现状:对于在企业环境中的访问控制方法,一般有三种:1.自主型访问控制方法。目前在我国的大多数的信息系统中的访问控制模块中基本是借助于自主型访问控制方法中的访问控制列表(ACLs)。2.强制型访问控制方法。用于多层次安全级别的军事应用。3.基于角色的访问控制方法(RBAC)。是目前公认的解决大型企业的统一资源访问控制的有效方法。其显著的两大特征是:1.减小授权管理的复杂性,降低管理开销。2.灵活地支持企业的安全策略,并对企业的变化有很大的伸缩性。名词:粗粒度:表示类别级,即仅考虑对象的类别(the type of object),不考虑对象的某个特定实例。比如,用户管理中,创建、删除,对所有的用户都一视同仁,并不区分操作的具体对象实例。细粒度:表示实例级,即需要考虑具体对象的实例(the instance of object),当然,细粒度是在考虑粗粒度的对象类别之后才再考虑特定实例。比如,合同管理中,列表、删除,需要区分该合同实例是否为当前用户所创建。原则:权限逻辑配合业务逻辑。即权限系统以为业务逻辑提供服务为目标。相当多细粒度的权限问题因其极其独特而不具通用意义,它们也能被理解为是“业务逻辑”的一部分。比如,要求:“合同资源只能被它的创建者删除,与创建者同组的用户可以修改,所有的用户能够浏览”。这既可以认为是一个细粒度的权限问题,也可以认为是一个业务逻辑问题。在这里它是业务逻辑问题,在整个权限系统的架构设计之中不予过多考虑。当然,权限系统的架构也必须要能支持这样的控制判断。或者说,系统提供足够多但不是完全的控制能力。即,设计原则归结为:“系统只提供粗粒度的权限,细粒度的权限被认为是业务逻辑的职责”。需要再次强调的是,这里表述的权限系统仅是一个“不完全”的权限系统,即,它不提供所有关于权限的问题的解决方法。它提供一个基础,并解决那些具有“共性”的(或者说粗粒度的)部分。在这个基础之上,根据“业务逻辑”的独特权限需求,编码实现剩余部分(或者说细粒度的)部分,才算完整。回到权限的问题公式,通用的设计仅解决了Who+What+How 的问题,其他的权限问题留给业务逻辑解决。概念:Who:权限的拥用者或主体(Principal、User、Group、Role、Actor等等)What:权限针对的对象或资源(Resource、Class)。How:具体的权限(Privilege, 正向授权与负向授权)。Role:是角色,拥有一定数量的权限。Operator:操作。表明对What的How 操作。说明:User:与 Role 相关,用户仅仅是纯粹的用户,权限是被分离出去了的。User是不能与 Privilege 直接相关的,User 要拥有对某种资源的权限,必须通过Role去关联。解决 Who 的问题。Resource:就是系统的资源,比如部门新闻,文档等各种可以被提供给用户访问的对象。资源可以反向包含自身,即树状结构,每一个资源节点可以与若干指定权限类别相关可定义是否将其权限应用于子节点。Privilege:是Resource Related的权限。就是指,这个权限是绑定在特定的资源实例上的。比如说部门新闻的发布权限,叫做"部门新闻发布权限"。这就表明,该Privilege是一个发布权限,而且是针对部门新闻这种资源的一种发布权限。Privilege是由Creator在做开发时就确定的。权限,包括系统定义权限和用户自定义权限用户自定义权限之间可以指定排斥和包含关系(如:读取,修改,管理三个权限,管理 权限 包含 前两种权限)。Privilege 如"删除" 是一个抽象的名词,当它不与任何具体的 Object 或 Resource 绑定在一起时是没有任何意义的。拿新闻发布来说,发布是一种权限,但是只说发布它是毫无意义的。因为不知道发布可以操作的对象是什么。只有当发布与新闻结合在一起时,才会产生真正的 Privilege。这就是 Privilege Instance。权限系统根据需求的不同可以延伸生很多不同的版本。Role:是粗粒度和细粒度(业务逻辑)的接口,一个基于粗粒度控制的权限框架软件,对外的接口应该是Role,具体业务实现可以直接继承或拓展丰富Role的内容,Role不是如同User或Group的具体实体,它是接口概念,抽象的通称。Group:用户组,权限分配的单位与载体。权限不考虑分配给特定的用户。组可以包括组(以实现权限的继承)。组可以包含用户,组内用户继承组的权限。Group要实现继承。即在创建时必须要指定该Group的Parent是什么Group。在粗粒度控制上,可以认为,只要某用户直接或者间接的属于某个Group那么它就具备这个Group的所有操作许可。细粒度控制上,在业务逻辑的判断中,User仅应关注其直接属于的Group,用来判断是否“同组” 。Group是可继承的,对于一个分级的权限实现,某个Group通过“继承”就已经直接获得了其父Group所拥有的所有“权限集合”,对这个Group而言,需要与权限建立直接关联的,仅是它比起其父Group需要“扩展”的那部分权限。子组继承父组的所有权限,规则来得更简单,同时意味着管理更容易。为了更进一步实现权限的继承,最直接的就是在Group上引入“父子关系”。User与Group是多对多的关系。即一个User可以属于多个Group之中,一个Group可以包括多个User。子Group与父Group是多对一的关系。Operator某种意义上类似于Resource + Privilege概念,但这里的Resource仅包括Resource Type不表示Resource Instance。Group 可以直接映射组织结构,Role 可以直接映射组织结构中的业务角色,比较直观,而且也足够灵活。Role对系统的贡献实质上就是提供了一个比较粗颗粒的分配单位。Group与Operator是多对多的关系。各概念的关系图示如下:解释:Operator的定义包括了Resource Type和Method概念。即,What和How的概念。之所以将What和How绑定在一起作为一个Operator概念而不是分开建模再建立关联,这是因为很多的How对于某What才有意义。比如,发布操作对新闻对象才有意义,对用户对象则没有意义。How本身的意义也有所不同,具体来说,对于每一个What可以定义N种操作。比如,对于合同这类对象,可以定义创建操作、提交操作、检查冲突操作等。可以认为,How概念对应于每一个商业方法。其中,与具体用户身份相关的操作既可以定义在操作的业务逻辑之中,也可以定义在操作级别。比如,创建者的浏览视图与普通用户的浏览视图要求内容不同。既可以在外部定义两个操作方法,也可以在一个操作方法的内部根据具体逻辑进行处理。具体应用哪一种方式应依据实际情况进行处理。这样的架构,应能在易于理解和管理的情况下,满足绝大部分粗粒度权限控制的功能需要。但是除了粗粒度权限,系统中必然还会包括无数对具体Instance的细粒度权限。这些问题,被留给业务逻辑来解决,这样的考虑基于以下两点:一方面,细粒度的权限判断必须要在资源上建模权限分配的支持信息才可能得以实现。比如,如果要求创建者和普通用户看到不同的信息内容,那么,资源本身应该有其创建者的信息。另一方面,细粒度的权限常常具有相当大的业务逻辑相关性。对不同的业务逻辑,常常意味着完全不同的权限判定原则和策略。相比之下,粗粒度的权限更具通用性,将其实现为一个架构,更有重用价值;而将细粒度的权限判断实现为一个架构级别的东西就显得繁琐,而且不是那么的有必要,用定制的代码来实现就更简洁,更灵活。所以细粒度控制应该在底层解决,Resource在实例化的时候,必需指定Owner和GroupPrivilege在对Resource进行操作时也必然会确定约束类型:究竟是OwnerOK还是GroupOK还是AllOK。Group应和Role严格分离User和Group是多对多的关系,Group只用于对用户分类,不包含任何Role的意义;Role只授予User,而不是Group。如果用户需要还没有的多种Privilege的组合,必须新增Role。Privilege必须能够访问Resource,同时带User参数,这样权限控制就完备了。思想:权限系统的核心由以下三部分构成:1.创造权限,2.分配权限,3.使用权限,然后,系统各部分的主要参与者对照如下:1.创造权限 - Creator创造,2.分配权限 - Administrator 分配,3.使用权限 - User:1. Creator 创造 Privilege, Creator 在设计和实现系统时会划分,一个子系统或称为模块,应该有哪些权限。这里完成的是 Privilege 与 Resource 的对象声明,并没有真正将 Privilege 与具体Resource 实例联系在一起,形成Operator。2. Administrator 指定 Privilege 与 Resource Instance 的关联。在这一步, 权限真正与资源实例联系到了一起, 产生了Operator(Privilege Instance)。Administrator利用Operator这个基本元素,来创造他理想中的权限模型。如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联等等...这些操作都是由 Administrator 来完成的。3. User 使用 Administrator 分配给的权限去使用各个子系统。Administrator 是用户,在他的心目中有一个比较适合他管理和维护的权限模型。于是,程序员只要回答一个问题,就是什么权限可以访问什么资源,也就是前面说的 Operator。程序员提供 Operator 就意味着给系统穿上了盔甲。Administrator 就可以按照他的意愿来建立他所希望的权限框架可以自行增加,删除,管理Resource和Privilege之间关系。可以自行设定用户User和角色Role的对应关系。(如果将 Creator看作是 Basic 的发明者, Administrator 就是 Basic 的使用者,他可以做一些脚本式的编程) Operator是这个系统中最关键的部分,它是一个纽带,一个系在Programmer,Administrator,User之间的纽带。用一个功能模块来举例子。一.建立角色功能并做分配:1.如果现在要做一个员工管理的模块(即Resources),这个模块有三个功能,分别是:增加,修改,删除。给这三个功能各自分配一个ID,这个ID叫做功能代号:Emp_addEmp,Emp_deleteEmp,Emp_updateEmp。2.建立一个角色(Role),把上面的功能代码加到这个角色拥有的权限中,并保存到数据库中。角色包括系统管理员,测试人员等。3.建立一个员工的账号,并把一种或几种角色赋给这个员工。比如说这个员工既可以是公司管理人员,也可以是测试人员等。这样他登录到系统中将会只看到他拥有权限的那些模块。二.把身份信息加到Session中。登录时,先到数据库中查找是否存在这个员工,如果存在,再根据员工的sn查找员工的权限信息,把员工所有的权限信息都入到一个Hashmap中,比如就把上面的Emp_addEmp等放到这个Hashmap中。然后把Hashmap保存在一个UserInfoBean中。最后把这个UserInfoBean放到Session中,这样在整个程序的运行过程中,系统随时都可以取得这个用户的身份信息。三.根据用户的权限做出不同的显示。可以对比当前员工的权限和给这个菜单分配的“功能ID”判断当前用户是否有打开这个菜单的权限。例如:如果保存员工权限的Hashmap中没有这三个ID的任何一个,那这个菜单就不会显示,如果员工的Hashmap中有任何一个ID,那这个菜单都会显示。 对于一个新闻系统(Resouce),假设它有这样的功能(Privilege):查看,发布,删除,修改;假设对于删除,有"新闻系统管理者只能删除一月前发布的,而超级管理员可删除所有的这样的限制,这属于业务逻辑(Business logic),而不属于用户权限范围。也就是说权限负责有没有删除的Permission,至于能删除哪些内容应该根据UserRole or UserGroup来决定(当然给UserRole or UserGroup分配权限时就应该包含上面两条业务逻辑)。一个用户可以拥有多种角色,但同一时刻用户只能用一种角色进入系统。角色的划分方法可以根据实际情况划分,按部门或机构进行划分的,至于角色拥有多少权限,这就看系统管理员赋给他多少的权限了。用户—角色—权限的关键是角色。用户登录时是以用户和角色两种属性进行登录的(因为一个用户可以拥有多种角色,但同一时刻只能扮演一种角色),根据角色得到用户的权限,登录后进行初始化。这其中的技巧是同一时刻某一用户只能用一种角色进行登录。针对不同的“角色”动态的建立不同的组,每个项目建立一个单独的Group,对于新的项目,建立新的 Group 即可。在权限判断部分,应在商业方法上予以控制。比如:不同用户的“操作能力”是不同的(粗粒度的控制应能满足要求),不同用户的“可视区域”是不同的(体现在对被操作的对象的权限数据,是否允许当前用户访问,这需要对业务数据建模的时候考虑权限控制需要)。扩展性:有了用户/权限管理的基本框架,Who(User/Group)的概念是不会经常需要扩展的。变化的可能是系统中引入新的 What (新的Resource类型)或者新的How(新的操作方式)。那在三个基本概念中,仅在Permission上进行扩展是不够的。这样的设计中Permission实质上解决了How 的问题,即表示了“怎样”的操作。那么这个“怎样”是在哪一个层次上的定义呢?将Permission定义在“商业方法”级别比较合适。比如,发布、购买、取消。每一个商业方法可以意味着用户进行的一个“动作”。定义在商业逻辑的层次上,一方面保证了数据访问代码的“纯洁性”,另一方面在功能上也是“足够”的。也就是说,对更低层次,能自由的访问数据,对更高层次,也能比较精细的控制权限。确定了Permission定义的合适层次,更进一步,能够发现Permission实际上还隐含了What的概念。也就是说,对于What的How操作才会是一个完整的Operator。比如,“发布”操作,隐含了“信息”的“发布”概念,而对于“商品”而言发布操作是没有意义的。同样的,“购买”操作,隐含了“商品”的“购买”概念。这里的绑定还体现在大量通用的同名的操作上,比如,需要区分“商品的删除”与“信息的删除”这两个同名为“删除”的不同操作。提供权限系统的扩展能力是在Operator (Resource + Permission)的概念上进行扩展。Proxy 模式是一个非常合适的实现方式。实现大致如下:在业务逻辑层(EJB Session Facade [Stateful SessionBean]中),取得该商业方法的Methodname,再根据Classname和 Methodname 检索Operator 数据,然后依据这个Operator信息和Stateful中保存的User信息判断当前用户是否具备该方法的操作权限。应用在 EJB 模式下,可以定义一个很明确的 Business层次,而一个Business 可能意味着不同的视图,当多个视图都对应于一个业务逻辑的时候,比如,Swing Client以及 Jsp Client 访问的是同一个 EJB 实现的 Business。在 Business 层上应用权限较能提供集中的控制能力。实际上,如果权限系统提供了查询能力,那么会发现,在视图层次已经可以不去理解权限,它只需要根据查询结果控制界面就可以了。灵活性:Group和Role,只是一种辅助实现的手段,不是必需的。如果系统的Role很多,逐个授权违背了“简单,方便”的目的,那就引入Group,将权限相同的Role组成一个Group进行集中授权。Role也一样,是某一类Operator的集合,是为了简化针对多个Operator的操作。Role把具体的用户和组从权限中解放出来。一个用户可以承担不同的角色,从而实现授权的灵活性。当然,Group也可以实现类似的功能。但实际业务中,Group划分多以行政组织结构或业务功能划分;如果为了权限管理强行将一个用户加入不同的组,会导致管理的复杂性。Domain的应用。为了授权更灵活,可以将Where或者Scope抽象出来,称之为Domain,真正的授权是在Domain的范围内进行,具体的Resource将分属于不同的Domain。比如:一个新闻机构有国内与国外两大分支,两大分支内又都有不同的资源(体育类、生活类、时事政治类)。假如所有国内新闻的权限规则都是一样的,所有国外新闻的权限规则也相同。则可以建立两个域,分别授权,然后只要将各类新闻与不同的域关联,受域上的权限控制,从而使之简化。权限系统还应该考虑将功能性的授权与资源性的授权分开。很多系统都只有对系统中的数据(资源)的维护有权限控制,但没有对系统功能的权限控制。权限系统最好是可以分层管理而不是集中管理。大多客户希望不同的部门能且仅能管理其部门内部的事务,而不是什么都需要一个集中的Administrator或Administrators组来管理。虽然你可以将不同部门的人都加入Administrators组,但他们的权限过大,可以管理整个系统资源而不是该部门资源。正向授权与负向授权:正向授权在开始时假定主体没有任何权限,然后根据需要授予权限,适合于权限要求严格的系统。负向授权在开始时假定主体有所有权限,然后将某些特殊权限收回。权限计算策略:系统中User,Group,Role都可以授权,权限可以有正负向之分,在计算用户的净权限时定义一套策略。系统中应该有一个集中管理权限的AccessService,负责权限的维护(业务管理员、安全管理模块)与使用(最终用户、各功能模块),该AccessService在实现时要同时考虑一般权限与特殊权限。虽然在具体实现上可以有很多,比如用Proxy模式,但应该使这些Proxy依赖于AccessService。各模块功能中调用AccessService来检查是否有相应的权限。所以说,权限管理不是安全管理模块自己一个人的事情,而是与系统各功能模块都有关系。每个功能模块的开发人员都应该熟悉安全管理模块,当然,也要从业务上熟悉本模块的安全规则。技术实现:1.表单式认证,这是常用的,但用户到达一个不被授权访问的资源时,Web容器就发出一个html页面,要求输入用户名和密码。 2.一个基于Servlet Sign in/Sign out来集中处理所有的Request,缺点是必须由应用程序自己来处理。3.用Filter防止用户访问一些未被授权的资源,Filter会截取所有Request/Response,然后放置一个验证通过的标识在用户的Session中,然后Filter每次依靠这个标识来决定是否放行Response。这个模式分为:Gatekeeper :采取Filter或统一Servlet的方式。Authenticator: 在Web中使用JAAS自己来实现。用户资格存储LDAP或数据库:1. Gatekeeper拦截检查每个到达受保护的资源。首先检查这个用户是否有已经创建好的Login Session,如果没有,Gatekeeper 检查是否有一个全局的和Authenticator相关的session?2. 如果没有全局的session,这个用户被导向到Authenticator的Sign-on 页面,要求提供用户名和密码。3. Authenticator接受用户名和密码,通过用户的资格系统验证用户。4. 如果验证成功,Authenticator将创建一个全局Login session,并且导向Gatekeeper来为这个用户在他的web应用中创建一个Login Session。5. Authenticator和Gatekeepers联合分享Cookie,或者使用Tokens在Query字符里。  引用  报告 回复 500)this.width=500'> naddy 超级版主500)this.width=500'>500)this.width=500'>超级大白鲨 500)this.width=500'>500)this.width=500'>   500)this.width=500'>   UID 13精华 3 积分 1430帖子 192经验 1430 点威望 0 点金钱 1850 ¥魅力 814 点券 0 ¥阅读权限 150注册 1970-1-1状态 离线 #2 使用道具   发表于 1970-1-1 08:00  资料  个人空间  短消息  加为好友  500)this.width=500'> 转 Programmer's Life 关于权限管理的文章 目录结构一. 概述 二. 目的 三. 需求 3.1. 描述 3.2. 分析 四. 实现方案 4.1. 技术策略 4.2. 基于RBAC的实现 4.2.1. RBAC介绍 4.2.2. 实现方案 4.2.3. 优缺点分析 4.3. 基于ACL的实现 4.3.1. ACL介绍 4.3.2. 实现方案 4.3.3. 优缺点分析 五. 开源产品 六. 个人观点 一. 概述 本文根据对中小型应用系统的权限系统的需求进行阐述,并对通常用于实现权限系统的两种思想、技术策略以及技术实现方案进行描述,比较其优缺点,同时对开源类型的产品进行介绍,最后结合自己的实际经验介绍自己的实现方案以及碰到的难点。 本文并不是什么理论化的文章,完全是实战型的总结和实战的讨论,至于理论请大家去参考更为专业的文章。 二. 目的 此文的编写作为自己对于权限系统进行系统化的整理,毕竟权限系统是几乎所有系统中都需要的,但一直以来由于在权限系统上并没有什么通用的方案,所以几乎是N多的人都实现了自己的一套,在此我也是抛砖引玉。 三. 需求 3.1. 描述 这里对于需求的描述都是基于自己工作以来实际项目需求的经验而综合的,如有遗漏之处欢迎大家补充,不过也希望大家明白范围,是指中小型系统,至于大型的企业系统从来就没做过,我也无从提出需求。 从一个实际的场景来描述一般中小型系统中涉及的权限需求吧,在通常的B/S系统中,首页列出不需登录可访问的信息,登录后则根据用户拥有的权限显示相应的菜单,在具体菜单对应的模块里根据用户的权限显示相应权限的按钮,同时显示当前用户可访问的相应的资源。 非功能性的需求: l 简便的授权方式。避免每增加一个用户就要不断的去授予N多的权限,避免相同权限的用户还要去相同的授予,提供出分组的功能。 l 权限的继承。在上面提出分组的功能后考虑到组应支持嵌套功能,即子组自动继承父组的权限,这样授权时就更加简便了。 l 高性能。不能因为校验权限而严重影响到系统的性能。 l 安全性。除正常途径方式访问系统的保护外,也需要避免通过非正常的途径访问系统中受保护的资源。 除了这些用户通常直接提出的需求外,在实际的项目中通常还会有这些需求: l 权限的排斥和包含。用户在实际的使用后通常会提出这个需求,权限的排斥主要是指当用户拥有权限A时则不能同时再拥有权限B,这个在实现了权限继承的系统中尤为突出;权限的包含主要指当用户拥有权限A时自动拥有了权限B,实际的例子是当用户拥有管理权限时自动同时拥有访问权限。 l 系统资源权限的继承。在对带有分级性质的资源进行授权时子资源自动继承父资源的权限,这个在文档管理类型的系统中比较常见,即目录中的文档自动拥有目录的权限。 l 系统资源权限的多种授予对象。通常系统的权限是授予到角色中,而对于系统资源的权限授予上用户在使用后通常会提出需要授予到多种对象,除角色之外还需可授予给组织机构或者具体的用户。 3.2. 分析 对需求中列出的场景进行分析: l 上下文 未登录用户、登录用户、管理用户不同的界面等情况。 l 问题 如何识别是否为登录用户、管理用户或未登录用户。 l 解决方案 提供身份认证功能,通过此功能标识用户身份。 l 上下文 根据用户拥有的权限显示相应的菜单,在具体菜单对应的模块里根据用户的权限显示相应权限的按钮。 l 问题 由于菜单或者按钮都是通过触发链接或命令的方式来实现其功能,那么在权限系统中需要做到的即可通过判断用户是否具有执行此链接或命令的权限来实现对于菜单和按钮的显示的控制。 这样带来的问题就是如何判断用户是否拥有执行某链接或命令的权限以及如何根据此结果去隐藏菜单和按钮的显示。 l 解决方案 提供校验用户是否拥有执行某链接和命令的权限的功能。 提供控制菜单、按钮显示的功能。 l 上下文 显示当前用户可访问的相应的资源,有两种情况,一种是全部显示,一种是分页显示。 l 问题 如何判断用户可访问哪些资源,资源如何进行分页处理。 l 解决方案 提供获取用户权限范围内的资源的功能,并提供全部获取和分页获取两种方式。 l 上下文 简便的授权方式。 l 问题 为提升用户授权的简便性,将权限授予给角色或组,用户只需要属于这个角色或组即可拥有相应的权限。 如何建立满足需求的授权模型。 l 解决方案 根据需求建立相应的授权模型。 根据对需求的分析,可以得出权限系统需要做到如下的功能: l 用户身份认证。 l 校验用户是否拥有执行某链接和命令的权限的功能。 l 控制菜单、按钮显示的功能。 l 获取用户权限范围内的资源的功能,并提供全部获取和分页获取两种方式。 l 建立相应的授权模型。 在非功能性需求方面权限系统需要考虑如下几个方面: l 权限的继承。 l 权限的排斥和包含。 l 高性能。 l 安全性。 l 系统数据的权限的继承。 l 系统数据的多种授权对象的支持。 根据这些对权限系统的功能需求和非功能性需求,我们可以合并和归纳成如下的一个表格作为对权限系统的需求: 功能点 描述 身份认证 提供用户身份认证的功能,以标识用户是否登录、是否为管理员等身份。 资源权限校验 判断操作主体是否具有对某资源进行某操作的权限。 数据权限校验 获取用户权限范围内的数据的功能,并提供全部获取和分页获取两种方式。 系统数据的权限的继承。 系统数据的多种授权对象的支持。 授权模型 系统权限的授予模型决定了权限系统使用的易用与否。 权限的继承。 权限的排斥和包含。 权限校验的体现 控制菜单、按钮的显示。 高性能 高效的授权与高效的权限校验。 安全性 防止非法途径对于系统受保护资源的访问或操作。 根据上面的需求描述以及对需求的分析,我们得知通常的一个中小型系统对于权限系统所需实现的功能以及非功能性的需求,在下面我们将根据需求从技术角度上分析实现的策略以及基于目前两种比较流行的权限设计思想来讨论关于权限系统的实现。 1.1. 技术策略 l 身份认证 在B/S的系统中,为识别用户身份,通常使用的技术策略为将用户的身份记录在Session中,也就是当用户登录时即获取用户的身份信息,并将其记录到Session里,当需要进行身份认证的时候通过从Session中获取用户的身份信息来实现用户的身份认证。 l 资源权限校验 资源权限校验取决于系统的授权模型,这块将在之后进行详细的阐述。 l 数据权限校验 数据权限校验取决于系统的授权模型,这块将在之后进行详细的阐述。 l 授权模型 授权模型作为权限系统的核心,从本质上决定了权限系统的易用性,这个易用性包括权限的授予和权限的校验,并同时也决定了权限的继承,权限的排斥和包含等方面的实现。 在经历了这么多年的发展,授权模型在目前中小型应用系统接受的比较多的主要有RBAC模型和ACL模型,将在之后展开专门的篇幅进行讲解。 l 权限校验的体现 权限校验的体现在中小型系统中体现出来的通常只是对于系统菜单、按钮显示的控制和对于拥有权限的数据的访问上。 它们共同依赖于资源权限校验和数据权限校验,对于系统菜单、按钮的显示上的控制在B/S中通常采用的技术策略为在生成菜单、按钮的Html时做权限级的判断,当操作主体不具备权限时则不生成该菜单、按钮的Html,从技术角度分析为方便使用者,避免使用者调用权限校验接口,通常的做法为提供菜单、按钮的标签,通过此标签生成的菜单和按钮即为经过权限过滤的。 l 高性能 为提高权限系统在授权以及校验权限时的性能,通常的做法为采用缓存技术以及加强权限系统的管理建设,加强权限系统的管理建设有助于建立一个最为适合需求的权限结构,同时做到了简化系统权限授予。 l 安全性 安全性方面来讲在B/S系统中通常有两个方面需要控制: n 通过非法途径访问系统文件 在Java的Web应用中通常采用的技术策略为将需要受保护的文件放入WEB-INF文件夹中,大家都知道在WEB-INF下的文件除了在服务器上能直接访问外,通过普通的URL是无法访问到的。 其次的做法为做Filter,即对需要受保护的资源做访问的Filter,如操作者不具备权限则直接报出错误。 n 通过非法途径访问系统操作 通常采用的技术策略为对每个直接暴露对外的需要受权限保护的对象做操作级别的权限控制,简单来说在Web系统中通常采用MVC框架来实现,通常Command层是直接对外的,为防止用户通过URL或其他方式访问Command,从技术上我们需要考虑对现有系统的尽量少的侵入性,所以通常采用的做法是在Command之上做Before Interceptor或Proxy,在此Interceptor或Proxy中做权限的校验,以确认操作者具有相应的权限。 经过上面的描述,我们已经基本了解到满足权限系统需求的技术实现策略,从中我们也可以看出权限系统中最为重要的为授权模型,由于权限系统的通用性,在业界也是推出了不少的授权模型,在这里我们已目前比较通用的两种授权模型来具体讲解权限系统的完整实现。 1.2. 基于RBAC的实现 1.2.1. RBAC介绍 RBAC模型作为目前最为广泛接受的权限模型,在此也将对其模型进行简要的介绍,RBAC模型成功的经典应用案例当属Unix系统了。 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所示。 500)this.width=500'>图表 1 RBAC 0模型 l RBAC0定义了能构成一个RBAC控制系统的最小的元素集合 在RBAC之中,包含用户users(USERS)、角色roles(ROLES)、目标objects(OBS)、操作operations(OPS)、许可权permissions(PRMS)五个基本数据元素,权限被赋予角色,而不是用户,当一个角色被指定给一个用户时,此用户就拥有了该角色所包含的权限。会话sessions是用户与激活的角色集合之间的映射。RBAC0与传统访问控制的差别在于增加一层间接性带来了灵活性,RBAC1、RBAC2、RBAC3都是先后在RBAC0上的扩展。 l RBAC1引入角色间的继承关系 角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构。 l RBAC2模型中添加了责任分离关系 RBAC2的约束规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。约束与用户-角色-权限关系一起决定了RBAC2模型中用户的访问许可。 l RBAC3包含了RBAC1和RBAC2 既提供了角色间的继承关系,又提供了责任分离关系。 1.2.2. 实现方案 通过上面章节对RBAC的介绍,从RBAC模型中我们可以看出它已经实现了一个使用起来很方便的授权模型,并同时也就权限的继承,权限的排斥和包含提出了解决的模型。 那么现在的关键是我们需要来看看基于RBAC到底是怎么实现权限系统的需求的呢?在这里我们针对在技术策略中未描述的授权模型和权限校验部分做实现方案的讲解。 l 授权模型 授权模型遵循RBAC进行搭建,即建立如上图表一的模型。 针对授权模型中的几个关键部分我们进行描述: n 授权 按照RBAC的模型,在授权时分为配置资源以及资源的操作、授予角色对资源的操作权限、分配角色给用户这几个步骤来完成。 从这几个步骤我们进行分析: u 配置资源以及资源的操作 实现这步非常的简单,直接维护资源以及资源操作两个对象的持久即可实现。 u 授予角色对资源的操作权限 实现这步同样非常的简单,维护角色与资源的关联模型即可。 u 分配角色给用户 实现这步同样非常的简单,维护角色与用户的关联模型即可。 n 权限的继承 权限的继承在RBAC的模型中通过增加角色的自关联来实现,即角色可拥有子角色,子角色继承父角色的权限。 按照此模型可以看出在授权时维护权限的继承也是非常的简单,维护角色的自关联模型即可。 n 权限的排斥和包含 权限的排斥和包含这块我没有具体看RBAC的规范,通常的做法是通过在资源的操作权限模型中增加自关联模型以定义哪些资源的操作权限是排斥和包含的,在授权时可以看到同样需要维护的只是资源权限的自关联模型。 l 资源权限校验 根据上面的授权模型,在做资源权限校验的时候需要经过以下步骤: n 判断用户所在的角色是否拥有对资源进行操作的权限 获取用户所拥有的角色,遍历其角色,以各角色建立Session,并通过类似的role.doPrivilege(Resource,Operation)的方式来判断该角色是否具备权限,如具备则直接返回,如不具备则直到遍历结束。 n 递规用户所在角色的父角色判断是否拥有对资源进行操作的权限 当遍历完用户本身的角色得到用户不具备对资源进行该操作的权限时,则开始递规其所在角色的父角色来判断是否拥有对资源进行操作的权限,过程同上,如确定某角色具备,则返回,如不具备直到递规结束。 l 数据权限校验 在RBAC模型中没有明确定义数据权限的实现策略,鉴于此首先要讲解下基于RBAC模型的数据授权模型的建立,基于RBAC模型,将数据映射为RBAC中的资源,对数据的操作则映射为资源的操作,同样的是将此资源以及资源的操作构成的权限授予给角色,将用户分配给角色完成数据权限的授权过程。 但根据数据权限校验的需求,数据的权限也是需要继承的,而且数据权限的授予对象需要是多种,这样的话就对上面根据RBAC映射形成的数据权限的授权模型造成了冲击,需要重构上面的授权模型来满足需求。 为实现数据权限的继承,需要将RBAC模型中的资源重构为允许自关联的模型,为实现数据权限能够授予给多种对象,需要将本来资源操作权限授予给角色的模型演变为数据操作权限授予给角色、组织机构或具体人员,根据RBAC模型,同样的建立一个中间对象,此对象和数据操作权限所授予的对象做1对多的关联,在经过这样的重构之后数据权限的授权模型就形成了,也满足了数据权限的继承和授予给多种对象的需求。 500)this.width=500'>图表 2 基于RBAC演变的数据权限模型 上面的图中少画了数据的自关联。根据上面的数据权限模型,来看看数据权限的校验是怎么样去实现呢? 在做数据权限校验的时候我们需要实现的为两种方式,一种是获取操作主体具有数据操作权限的全部数据,另外一种为分页获取操作主体具有数据操作权限的数据。 就这两种方式分别来进行阐述: n 获取操作主体具有数据操作权限的全部数据 从数据库中获取所有数据,遍历取出的数据从数据权限模型中获取相应的拥有数据操作权限的权限拥有者,如果该数据未配置数据操作权限的控制,那么就无需对该数据进行权限级的判断,如配置了,则需判断当前用户是否在该数据操作权限所对应的拥有者中,如用户不在,则需递规获取该数据的父数据的操作权限的拥有者,到用户拥有权限或递规结束时终止。 n 分页获取操作主体具有数据操作权限的数据 分页的做法和上面差不多,只是在获取了所有的数据后在内存中做分页返回。 1.2.3. 优缺点分析 从上面的基于RBAC的实现方案中可以看出基于RBAC模型的优点在于: l 易用和高效的授权方式 用户在进行授权时只需对角色进行授权,之后将相应的角色分配给用户即可。 l 简便和高效的授权模型维护 在技术角度来讲,进行授权模型的维护上因为基本只需要维护关联模型而显得简单而高效。 缺点在于: l 复杂的权限校验 在进行权限校验时需要不断的遍历和递规,造成了性能的影响。 l 对于数据权限的不够支持没有明确的数据权限模型,可以看到在经过重构的数据权限模型其实已经和RBAC模型有一定的 出入,而且在数据权限的校验上实现起来是非常的低效。 基于ACL的实现 ACL介绍 ACL全称Access Control List,在ACL中,包含用户(User)、资源(Resource)、资源操作(Operation)三个关键要素。通过将资源以及资源操作授权给用户而使用户获取对资源进行操作的权限,模型如下图所示: 500)this.width=500'>图表 1 ACL模型 实现方案 通过上面对ACL模型的介绍,可以看出ACL是个简单的模型,但其并未提出对于权限的继承、权限的排斥和包含的解决方案。 ACL模型得到接受必然也是有它的理由的,现在来看看基于ACL模型如何来实现授权模型和权限校验部分。 l 授权模型 授权模型遵循ACL模型进行搭建,建立ACL介绍中的模型。 针对授权模型中的几个关键部分进行描述: n 授权 根据ACL模型,授权动作主要经过以下几个步骤完成: u 配置系统资源和资源的操作 按照模型维护Resource、Operation实体以及Resource与Operation的关联模型即可实现。 u 授予用户能操作的资源和资源的操作 按照模型维护用户与Resource以及Operation的关联即可实现。 n 权限的继承 在ACL模型中未定义权限的继承,这也是由于在ACL的模型中根本就没有权限继承的点,因为用户本身是不可能继承的。 在很多改良的ACL模型系统中,会通过给组或组织机构授权来完成,这时就出现了权限继承的点了,如组或组织机构的权限继承,那么在ACL模型中如何去实现这个权限继承呢? 为实现给组或组织机构进行授权,此时通常需要对上述ACL模型进行改造方可实现,模型重构如下: 500)this.width=500'>图表 2 重构后的ACL模型 在对组或组织机构进行授权动作时,经过以下步骤来实现权限的继承: u 维护当前组或组织机构中所有用户的ACL模型 维护当前组或组织机构和Resource、Operation的关联模型。 递规获取当前组或组织机构的父节点的ACL模型,并合并形成新的Resource、Operation关联列表,此时获取该组或组织机构中的用户产生用户和Resource、Operation的关联ACL模型。 u 维护当前组或组织机构中所有下级节点中的所有用户的ACL模型 递规获取当前组或组织机构的子节点,同时合并形成子节点新的Resource、Operation关联列表,之后获取子节点中的用户产生新的Resource、Operation关联列表。 在经过以上的步骤后权限的继承得以实现,在使用过程中同时发现另外一个问题,在更新组或组织机构下的用户时需要同时维护当前组或组织机构的ACL模型,否则会造成不同步的问题。 n 权限的排斥和包含 权限的排斥和包含在ACL模型中同样没有定义,通常的实现方法是定义Operation的自关联,维护时需增加对Operation自关联的维护以及在维护User、Resource、Operation关联时根据Operation的自关联产生其包含权限的ACL列表。 l 资源权限校验 在以上授权模型的基础上,对于操作主体能否对资源进行操作权限的判断通过ACL列表直接判断用户是否具有对资源进行操作的权限即可。 通常在中小型系统的做法是在用户登录时获取构成用户的ACL列表,以提升资源权限校验的效率。 l 数据权限校验 在ACL模型中未明确定义数据权限校验的实现,根据数据权限校验的需求将数据映射为Resource,对数据的操作映射为Operation,这个时候数据权限的授权模型重构为: 500)this.width=500'>图表 3 数据权限的ACL模型 基于此模型对数据权限的授权和权限校验进行描述: n 授权 在对数据进行授权时根据模型此时的授权对象主要有User、Group两种,授权时需要通过以下步骤来完成: u 维护数据本身构成的ACL模型 维护当前数据、操作与Group、User的关联模型。 递规获取当前数据、操作的父节点的Group、User的关联模型,合并组成新的Group、User列表,根据此列表形成对当前数据进行操作的用户列表,此时更新形成UseràResourceàOperation的ACL列表模型。 u 维护数据所有子节点的ACL模型 递规获取数据的所有子节点,同时对合并形成每个子节点的新的Group、User列表,更新子节点的UseràResourceàOperation的ACL列表模型。 在经过以上的步骤后数据权限的继承以及需求得以实现,在使用过程中同时发现另外一个问题,在更新组或组织机构下的用户时需要同时维护当前组或组织机构的ACL模型,否则会造成不同步的问题。 n 权限校验 u 获取操作者权限范围内的全部数据 直接通过UseràResourceàOperation的ACL列表获取所有数据。 u 分页获取操作者权限范围内的数据 直接通过UseràResourceàOperation的ACL列表分页(结合数据库的分页技术)获取数据。 优缺点分析 经过上述实现方案的描述,可以看出基于ACL的实现的优点主要在于: n 易用和高效的权限校验 在进行资源和数据的权限校验时只需通过通过ACL列表即可实现。 缺点在于: n 权限的继承 对权限继承不够支持。 n 复杂和低效的授权方式 在进行资源和数据的授权时非常复杂,特别是在加入权限的继承、排斥和包含后,需要在维护本身ACL列表的同时维护所有子节点的ACL列表,导致效率低下。 一. 开源产品 对开源的产品了解不多,所以也只能大概的谈谈,开源的产品中比较知名的有poweracl、acegi,poweracl从名字就可以看出其是基于ACL模型的,不怎么了解所以在此也不去评价了。 Acegi作为JAVA界知名的权限系统,从其文档看来是能满足上述的权限系统的所有需求,其reference文档也对权限系统进行了系统的归纳,非常的不错,建议去看看。 在Acegi中授权模型以及资源权限的校验仍然是基于RBAC模型,在数据权限方面也就是在reference文档中它称为Domain Object Instance的部分,是基于ACL模型的实现,曾经翻阅它此部分的代码,根据代码表现它并不支持Domain Object Instance的权限的继承,并且对于获取的Domain Object Instance也是没法采用分页的方式获取。 看了Acegi的代码觉得其授权应该是比较高效的,但在校验权限上效率恐怕也会比较的低,因为权限的继承是在校验权限通过递规来实现的,虽然引入了缓存机制但仍然无法从根本上解决此问题,而且此缓存的维护也不是一件容易的事。 但Acegi的优点也不可忽略,作为权限系统有一个很容易产生的问题就是对原有系统产生非常大的侵入,并最终导致原有系统与此权限系统形成了非常强的耦合,Acegi在这点上则做的比较好,通过使用Filter、Interceptor以及AOP Weaver技术来尽量保证对原有系统最少的改动。 二. 个人观点 权限系统作为各种系统中都需要的一个子系统,具有很广的需求面,无论做什么系统,首要重要的仍然是需求,尽管权限系统在各个系统中都有需求,但仍然是不尽相同,所以首先要明确所面对的系统到底是一个什么样的系统,对于权限有什么样的需求,根据需求可以根据相应的实现方案来做出自己的设计。 权限系统主要由授权和校验权限两大部分组成,授权效率和校验权限的效率通常会产生冲突,个人觉得首先要保证校验权限的效率,毕竟系统需要校验权限的地方会非常的多,但授权动作相对来讲触发的会比较的少。 从技术需求上来讲,权限系统对外部系统而言最好做到黑盒的效果,为了减少对外部系统的侵入,在根据业务需求分析的基础上形成权限系统的输入和输出需求,从通常的功能需求角度来大致的阐述: 1. 身份认证 在B/S结构的系统中通常通过增加Filter来达到实现身份认证的功能,这样不会造成对原有系统的改动。 2. 授权模型 授权模型则需外部系统根据此模型建立相应的授权UI以及交互,当然,权限系统本身也可提供默认的实现方式。 3. 资源权限校验 在资源权限的校验上可通过Proxy或Before Interceptor的方式来做到对资源操作的权限控制。 4. 数据权限校验 在很多时候需要区分好数据权限和业务逻辑,不要将业务逻辑形式的数据控制也借用数据权限来实现,数据权限的引入很容易对现有的系统模块造成影响,在此块的设计上要特别注意避免造成对原有系统模块过多的侵入。 5. 权限校验的体现 在权限校验的体现上基本主要是表现在菜单、按钮以及数据的显示上,菜单、按钮通常通过标签的方式来控制,数据的显示控制则需结合数据权限校验部分来实现。 到现在为止也做了几个权限系统了,目前仍然没做出让自己满意的权限系统,此文作为抛砖引玉的文章,也希望大家能够给出自己所做的解决方案。 三. 涉及的知识体系 根据上面的描述以及结合自己的经验,形成搭建权限系统所需的知识体系: 500)this.width=500'>图表 6 权限系统知识体系


阅读全文(2678) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.031 second(s), page refreshed 144814695 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号