角色权限收藏 (转)

tmdusa (CSDN'er)

前言:
权限往往是一个极其复杂的问题,但也可简单表述为这样的逻辑表达式:判断“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字符里。

回复人: goody9807() ( 两星(中级)) 信誉:100 2004-8-5 8:58:23 得分: 40
 

 但凡涉及多用户不同权限的网络或者单机程序,都会有权限管理的问题,比较突出的是MIS系统。

下面我要说的是MIS系统权限管理的数据库设计及实现,当然,这些思路也可以推广开来应用,比如说在BBS中用来管理不同级别的用户权限。

权限设计通常包括数据库设计、应用程序接口(API)设计、程序实现三个部分。

这三个部分相互依存,密不可分,要实现完善的权限管理体系,必须考虑到每一个环节可行性与复杂程度甚至执行效率。

我们将权限分类,首先是针对数据存取的权限,通常有录入、浏览、修改、删除四种,其次是功能,它可以包括例如统计等所有非直接数据存取操作,另外,我们还可能对一些关键数据表某些字段的存取进行限制。除此,我想不出还有另外种类的权限类别。

完善的权限设计应该具有充分的可扩展性,也就是说,系统增加了新的其它功能不应该对整个权限管理体系带来较大的变化,要达到这个目的,首先是数据库设计合理,其次是应用程序接口规范。

我们先讨论数据库设计。通常我们使用关系数据库,这里不讨论基于Lotus产品的权限管理。

权限表及相关内容大体可以用六个表来描述,如下:
1 角色(即用户组)表:包括三个字段,ID,角色名,对该角色的描述;
2 用户表:包括三个或以上字段,ID,用户名,对该用户的描述,其它(如地址、电话等信息);
3 角色-用户对应表:该表记录用户与角色之间的对应关系,一个用户可以隶属于多个角色,一个角色组也可拥有多个用户。包括三个字段,ID,角色ID,用户ID;
4 限制内容列表:该表记录所有需要加以权限区分限制的数据表、功能和字段等内容及其描述,包括三个字段,ID,名称,描述;
5 权限列表:该表记录所有要加以控制的权限,如录入、修改、删除、执行等,也包括三个字段,ID,名称,描述;
6 权限-角色-用户对应表:一般情况下,我们对角色/用户所拥有的权限做如下规定,角色拥有明令允许的权限,其它一律禁止,用户继承所属角色的全部权限,在此范围内的权限除明令禁止外全部允许,范围外权限除明令允许外全部禁止。该表的设计是权限管理的重点,设计的思路也很多,可以说各有千秋,不能生搬硬套说某种方法好。对此,我的看法是就个人情况,找自己觉得合适能解决问题的用。

先说第一种也是最容易理解的方法,设计五个字段:ID,限制内容ID,权限ID,角色/用户类型(布尔型字段,用来描述一条记录记录的是角色权限还是用户权限),角色/用户ID,权限类型(布尔型字段,用来描述一条记录表示允许还是禁止)

好了,有这六个表,根据表六,我们就可以知道某个角色/用户到底拥有/禁止某种权限。

或者说,这么设计已经足够了,我们完全实现了所需要的功能:可以对角色和用户分别进行权限定制,也具有相当的可扩展性,比如说增加了新功能,我们只需要添加一条或者几条记录就可以,同时应用程序接口也无须改动,具有相当的可行性。但是,在程序实现的过程中,我们发现,使用这种方法并不是十分科学,例如浏览某个用户所拥有的权限时,需要对数据库进行多次(甚至是递归)查询,极不方便。于是我们需要想其它的办法。使用过Unix系统的人们都知道,Unix文件系统将对文件的操作权限分为三种:读、写和执行,分别用1、2、4三个代码标识,对用户同时具有读写权限的文件被记录为3,即1+2。我们也可以用类似的办法来解决这个问题。初步的想法是修改权限列表,加入一个字段:标识码,例如,我们可以将录入权限标识为1,浏览权限标识为2,修改权限标识为4,删除权限标识为8,执行权限标识为16,这样,我们通过权限累加的办法就可以轻易的将原本要分为几条记录描述的权限放在一起了,例如,假定某用户ID为1,库存表对应的限制内容ID为2,同时规定角色类型为0、用户类型为1,我们就可以将该用户具有录入、浏览、修改、删除库存表的权限描述为:2,15,1,1。

确实很简单,不是吗?甚至还有更过激的办法,将限制内容列表也加上一列,定义好标识码,这样,我们甚至可以用简单的一条记录描述某个用户具有的对全部内容所具有的全部权限了。当然,这样做的前提是限制内容数量比较小,不然,呵呵,2的n次方递增起来可是数量惊人,不容易解析的。

从表面上看,上述方法足以达到实现功能、简化数据库设计及实现的复杂度这个目的,但这样做有个弊端,我们所涉及的权限列表不是相互独立而是互相依赖的,比如说修改权限,其实是包含浏览权限的,例如,我们可能只是简单的设置用户对库存表存取的权限值为录入+修改+删除(1+4+8=13),但事实上,该用户具有(1+2+4+8=15)的权限,也就是说,在这种方案中,13=15。于是当我们调用API询问某用户是否具有浏览权限时,就必须判断该用户是否具有对该数据表的修改权限,因此,如果不能在程序中固化权限之间的包含关系,就不能利用应用程序接口简单的做出判断。但这与我们的目的“充分的可扩展性”矛盾。

这个问题如何解决?我想到了另外一种设置标识码的方法,那就是利用素数。我们不妨将录入、浏览、修改、删除、执行的基本标志码定为2,3,5,7,11,当遇到权限互相包含的时候,我们将它的标识码设定为两个(或多个)基本标志码的乘积,例如,可以将“修改”功能的标志码定为3*5=15,然后将所有的权限相乘,就得到了我们需要的最终权限标识值。这样,我们在询问用户是否具有某项权限的时候,只需要将最终的值分解成质因子,例如,我们可以定义一个用户具有录入+修改+删除库存表的权限为 2*15*7=2*3*5*7,即表示,该用户具有了对库存表录入+浏览+修改+删除权限。

当然,对权限列表我们使用上述方法的前提是权限列表记录条数不会太多并且关系不是十分复杂,否则,光是解析权限代码就要机器忽悠半宿:)

我希望以上的分析是正确且有效的(事实上,我也用这些的方法在不止一套系统中实现),但无论如何,我觉得如此实现权限管理,只是考虑了数据库设计和应用程序接口两部分内容,对于实现,还是显得很费劲。因此,我恳请有过类似设计、实现经验的同志们提出建设性的意见和修改建议。

另外,关于数据库设计的思路还有使用二维表的,这将在以后的时间里讨论,关于应用程序接口的设计和实现我也将在利用另外篇幅和大家共同探讨,代码将用类C语法实现(我不喜欢pascal,抱歉)

欢迎朋友们和我联系,mailto:berg@91search.com,也欢迎访问我和另外一位朋友共同建设的网站:http://www.91search.com,那里将有一个音乐搜索的工具软件提供下载。

回复人: janssenkm(正在贴鬼故事,却碰见了鬼)(!@#$%) ( 五级(中级)) 信誉:98 2004-8-5 9:16:37 得分: 40

基于角色的访问控制系统设计 
 
 
  (2004-7-23 17:06:00) 来源:CCW 作者:王久辉

  访问控制策略是大多数应用系统必须考虑的问题。本文提出的基于角色的访问控制是一种新型访问控制模型,它不仅能够实现传统访问控制的功能,同时还可以方便权限的管理,能够灵活地进行配置以适应系统的不同需求,提高系统的可扩展性,可资同类系统借鉴。

  基于角色的访问控制是一种新型访问控制模型,它的基本思想是将权限与角色联系起来,在系统中根据应用的需要为不同的工作岗位创建相应的角色,同时根据用户职务和责任指派合适的角色,用户通过所指派的角色获得相应的权限,实现对文件的访问。它支持最小特权、责任分离以及数据抽象三个基本的安全原则。

  这里的角色用一般业务系统中的术语来说,就是业务系统中的岗位、职位或者分工。它和用户组的最主要的区别在于,用户组是作为用户的一个集合来对待的,并不涉及它的授权许可;而角色则既是一个用户的集合,又是一个授权许可的集合。角色是指具有一定技能,可以执行某些工作的人员(或资源)集合。通过给成员赋予不同的角色,对成员的多职能进行表达,提供约束成员不同权限范围变化的依据。 为了满足企业内既存在信息共享又存在信息独立的实际情况,在角色体系中采用双枝生成模式,即整个角色体系的来源有两枝,其中一枝来自于相对固定的组织机构,是相对稳定的角色集合描述;另一枝在动态组合过程中动态创建,是更加依赖于动态项目和扩展需要而生成的,具有极大的时效性,随着项目或者企业扩展组合的变化会在活动态、冻结态和无效态之间变更。这样既保证了成员企业的相对独立性,又保证了与其他成员合作过程中的及时性和有效性。

  访问控制系统设计

  基于角色的访问控制设计需要一套既行之有效,又方便灵活的设计方案,要采用各种控制机制和保护技术。安全策略是设计安全可靠系统的准则,通常涉及下列几个方面:

  1. 安全保护策略

  安全策略是信息安全性的高级指导,策略出自对用户要求、设备环境、机构规则、法律约束等方面的详细研究。策略重要性在于指导作用。而机构是实现和执行各种策略的功能的集合。

  安全策略 安全管理人员根据需要定义各种角色,并设置合适的访问权限,而用户根据其责任和资历再被指派为不同的角色。如图1所示,角色可以看成是一个表达访问控制策略的语义结构,它可以表示承担特定工作的资格。


 

  安全保护机构 系统的安全保护机构基本上是与上面的安全策略相互适应的,保护机构应负责阻止一切物理破坏和用户可能的操作破坏,后者归结为主体可用何种方式访问哪些对象。

  安全管理的职责 安全管理有集中管理与分散管理两种。前者意指一切权利都由负责系统安全工作的专职人员或小组掌握,他(们)决定用户的访问权利,控制系统安全的一切方面。后者是指不同的管理员控制着系统安全的不同方面,管理系统的不同部分,决定不同用户的访问权利。

  访问控制策略 它提供决定用户访问权利的依据。其中最重要的一个普遍的原则是“需者方知策略”。按照这一原则授予用户的权利,是用户能完成工作的最小权利集合,故也称之为“最少特权策略”。

  信息流动控制 只限制用户的访问权利而不考虑数据流动是极其危险的,控制数据流动以防止无权用户在数据流动后获得访问权利。

  密码变换 对于非常机密数据可变换为密码存贮,使得不知道密码的入侵者无法破译所得到的数据密码。密码变换能防止泄密,但不能保护数据信息不被破坏。

  软硬结合保护 这是安全保护的基本策略,许多硬保护功能是软件难以实现的,有些即使能实现,效率也不高。

  对安全遭到破坏的响应 各种保护机构都有可能遭到破坏,因此系统必须制订检测破坏手段与处置措施。

  2. 基于角色的访问控制总体功能框架图


  安全管理控制核心是系统安全管理的核心控制部分,它在系统中控制整个系统的安全控制工作,由它决定系统是否启动安全管理,在什么情况下调用访问控制机构,根据情况编写访问规则,如何将已有的访问规则应用于控制存贮访问规则。

  基于角色的访问控制实例

  下面以一个办公自动化公文系统为例来具体介绍基于角色的访问控制系统的设计。这个即将建立的基于角色的访问控制的公文系统包括:电子公告牌系统、电子邮件系统和电子公文系统。

  1. 办公系统的角色定义

  根据分析,我们发现在办公系统中一个用户的角色,即其权限由以下几类信息组合而成:用户的行政级别、用户所属(辖)部门以及用户的业务角色。

  用户的级别从纵向以较粗的粒度来界定用户,级别的例子如局长、处长、一般员工,不同级别的用户具有不同的权限。

  用户所属(辖)部门则从另一个维度来定义用户的职权范围。在保密单位的办公系统的安全需求中,一个原则是用户只能查看和处理其业务范围内的事情,这个业务范围就是通过用户所属(辖)部门来表示的。

  系统提供的一种灵活的控制是通过业务角色这个概念来实施的。业务角色可以定义得相当细,用来描述上述级别和部门两种概念无法定义的权限。在某些具体的业务中,存在某些特殊的用户具有特殊的职权,如公文处理中的机要员,这种特殊的职权无法用上述的级别和范畴的概念来表达,比如机要员和外收发人员都属于一般工作人员,并且都属于同一个部门,但是他们在公文处理中的职权就有明显的不同,因此我们引入业务角色的概念。业务角色是针对某项具体业务的一个权限的集合,一个用户在不同的业务中可能负责不同的职能,因此允许一个用户具有多个业务角色。

  2. 具体实现

  如何根据应用的需求采用恰当的方式建立用户——角色——权限这三者之间多对多的映射关系,将是整个办公自动化系统安全可靠和高效运行的关键。此外,所建立的映射关系应提供灵活的配置功能,使映射关系具有可更改和可扩充性,以适应可能变化的应用需求,同时还可根据某些特殊需求来进行动态授权。

  为了实现基于角色的访问控制,这里定义了三张表来实现角色到用户、角色到权限的分配,如表1、2、3所示。


  在用户申请某操作时候,系统需要检测用户所拥有的角色集合,并且根据这些角色集合所包含的权限来判断该用户是否可以进行该操作,如果可行则置许可证发放标志为真,这种方式称为用户牵引方式。同时,系统为了执行某些静态约束,比如同一用户不能属于两个互斥的角色,还定义了互斥角色表。

  3. 相关权限管理

  (1) 动态授权与动态约束

  基于角色的访问控制中用户所拥有的权限具有相对的稳定性,但在公文处理中往往会出现某些特殊事件需要做特殊的处理,动态授权机制用来反映这一需求。

  例如,用户1出差,需要用户2在其出差期间代理其部分业务工作,这就需要用户2在限定的一段时间内获得他权限之外的权限。

  约束是基于角色的访问控制中重要的安全策略,是对用户执行权限的一些限制。静态约束在系统设计时定义,而动态约束在系统运行时执行。所谓动态授权就是系统在特殊工作状态下,将用户A的职权委托给用户B的特殊授权方式。动态约束其实是依照相关模型的安全策略对动态授权进行相应约束,防止动态授权滥用而带来安全隐患。

  (2) 集中授权管理

  集中授权管理是在多种业务系统组合的复杂系统中,每个业务系统集中在一个安全机构进行授权的管理方式。

  在基于角色的访问控制系统的基础上,可以进一步构建PMI系统,基于PMI(Privilege Management Infrastructure)的集中授权系统采用基于属性证书的授权模式,向各种应用系统提供与应用相关的授权服务管理,提供用户身份到应用授权的映射功能。

  授权管理基础设施PMI 在体系上可分为三级,分别是SOA中心、AA 中心和AA 代理点。在实际应用中这种分级体系可以灵活配置,可以是三级、二级或一级。

  一个中央授权框架将能够使管理得到大大简化。一个允许组织以集中方式对所有这些服务器的访问控制进行管理,并为用户在空间中提供单一登录的安全解决方案,可以使安全管理得到大大简化,并能够提升用户体验和提高工作效率。
 
(转贴:http://www.chinabbc.com.cn/anli/view.asp?newsid=2004723165955533&classid=112111)

回复人: devfan(小星) ( 五级(中级)) 信誉:100 2004-8-8 16:49:23 得分: 20

Forms身份验证基于角色的授权

一 身份验证

在web.config的<authentication>的设置还是一样:

<authentication mode="forms">
    <forms name=".ASPXAUTH " loginUrl="/login.aspx" timeout="30" path= "/">
    </forms>
</authentication>

/login.aspx验证用户合法性页面中,在验证了用户的合法性后,还要有个取得此用户属于哪些role的过程,这个看各个应用的本身如何设计的了,一般是在数据库中会有个use_role表,可以从数据库中获得此用户属于哪些role,在此不深究如何去获取用户对应的role,最后肯定能够获得的此用户对应的所有的role用逗号分割的一个字符串。
在上面的非基于角色的方法中,我们用了FormsAuthentication.RedirectFromLoginPage 方法来完成生成身份验证票,写回客户端,浏览器重定向等一系列的动作。这个方法会用一些确省的设置来完成一系列的动作,在基于角色的验证中我们不能用这一个方法来实现,要分步的做,以便将一些定制的设置加进来:

1. 首先要根据用户标示,和用户属于的角色的字符串来创建身份验证票
public FormsAuthenticationTicket(
int version, //设为1
string name, //用户标示
DateTime issueDate, //Cookie 的发出时间, 设置为 DateTime.Now
DateTime expiration, //过期时间
bool isPersistent, //是否持久性(根据需要设置,若是设置为持久性,在发出
cookie时,cookie的Expires设置一定要设置)
string userData, //这里用上面准备好的用逗号分割的role字符串
string cookiePath // 设为"/",这要同发出cookie的路径一致,因为刷新cookie
要用这个路径
);

FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket (1,"kent",DateTime.Now, DateTime.Now.AddMinutes(30), false,UserRoles,"/") ;

2. 生成身份验证票的Cookie
2.1 将身份验证票加密序列化成一个字符串
string HashTicket = FormsAuthentication.Encrypt (Ticket) ;
2.2 生成cookie
HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket) ;
FormsAuthentication.FormsCookieName 是用来获取web.config中设置的身份验证cookie的名字,缺省为" .ASPXAUTH".
若身份验证票中的isPersistent属性设置为持久类,则这个cookie的Expires属性一定要设置,这样这个cookie才会被做为持久cookie保存到客户端的cookie文件中.
3. 将身份验证票Cookie输出到客户端
通过Response.Cookies.Add(UserCookie) 将身份验证票Cookie附加到输出的cookie集合中,发送到客户端.
4. 重定向到用户申请的初试页面.

验证部分代码(这部分代码是在login.aspx页面上点击了登录按钮事件处理代码):

private void Buttonlogin_Click(object sender, System.EventArgs e)
{
     string user = TextBoxUser.Text; //读取用户名
     string password = TextBoxPassword.Text; //读取密码
     if(Confirm(user,password) == true) //confirm方法用来验证用户合法性的
    {
         string userRoles = UserToRole(user); //调用UserToRole方法来获取role字符串
         FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket (1,user,DateTime.Now,          DateTime.Now.AddMinutes(30), false,userRoles,"/") ; //建立身份验证票对象
         string HashTicket = FormsAuthentication.Encrypt (Ticket) ; //加密序列化验证票为字符串
         HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket) ;
//生成Cookie
          Context.Response.Cookies.Add (UserCookie) ; //输出Cookie
         Context.Response.Redirect (Context.Request["ReturnUrl"]) ; // 重定向到用户申请的初始页面
     }
    else
    {
        // 用户身份未被确认时的代码
    }
}
//此方法用来验证用户合法性的
private bool Confirm(string user,string password)
{
    //相应的代码
}
//此方法用来获得的用户对应的所有的role用逗号分割的一个字符串
private string UserToRole(string user)
{
    //相应的代码
}

二 基于角色访问授权

这里我们要做的是,将客户端保存的身份验证票中UserData中保存的表示角色的信息恢复到在服务端表示用户身份的GenericPrincipal对象中(记住,原来的验证过程中, GenericPrincipal对象只包含了用户信息,没有包含role信息)
一个Http请求的过程中,HttpApplication.AuthenticateRequest事件表示安全模块已建立用户标识,就是此用户的身份在web端已经建立起来, 在这个事件之后我们就可以获取用户身份信息了.
在HttpApplication.ResolveRequestCache事件之前,asp.net开始取得用户请求的页面,建立HttpHandler控制点,这时就已经要验证用户的权限了,所以恢复用户角色的工作只能在HttpApplication.AuthenticateRequest事件和HttpApplication.ResolveRequestCache事件之间的过程中做.
我们选择Application_AuthorizeRequest事件中做这个工作,可以在global.asax文件中处理HttpApplication的所有的事件,代码如下:

protected void Application_AuthorizeRequest(object sender, System.EventArgs e)
{
    HttpApplication App = (HttpApplication) sender;
     HttpContext Ctx = App.Context ; //获取本次Http请求相关的HttpContext对象
    if (Ctx.Request.IsAuthenticated == true) //验证过的用户才进行role的处理
    {
        FormsIdentity Id = (FormsIdentity)Ctx.User.Identity ;
        FormsAuthenticationTicket Ticket = Id.Ticket ; //取得身份验证票
        string[] Roles = Ticket.UserData.Split (',') ; //将身份验证票中的role数据转成字符串数组
        Ctx.User = new GenericPrincipal (Id, Roles) ; //将原有的Identity加上角色信息新建一个GenericPrincipal表示当前用户,这样当前用户就拥有了role信息
    }
}

访问者同时具有了user和role信息,就可以据此在web.config中用role来控制用户的访问权限了

回复人: bitsbird(一瓢.Net(与奥运同在)) ( 三星(高级)) 信誉:107 2004-8-8 16:55:50 得分: 10
 

回复人: bitsbird(一瓢.Net(与奥运同在)) ( 三星(高级)) 信誉:107 2004-8-8 16:55:50 得分: 10
权限一般做成枚举,用户表中有角色字段一个表,角色和权限是一个表,权限是一个表,角色一个表,判断的时候判断一下用户的角色是否有这个权限
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值