摘 要 应用Windows系统 .Net Framework 开发平台,采用自定义属性、类型及反射等技术,通过对不同应用系统的资源ID生成、访问方式,以及资源树访问接口的定义,给出一套简洁、实用的基于角色的用户权限管理系统的通用平台设计方案。
关键词 权限管理;角色;反射;自定义属性
计算机技术安全管理的范围很广,可以包括网络安全性、数据安全性、操作系统安全性以及应用程序安全性等。对一个多用户商用应用系统而言,系统的安全访问控制是必须的,系统不仅要满足功能性需求,还要满足安全性需求。系统的安全访问控制一般是通过用户认证和用户权限管理来实现。权限管理可简单表述为:判断“Who对What(Which)进行How的操作”的逻辑表达式是否为真。各类应用系统的整个体系结构上要设计一个安全可靠、配置灵活、易扩展的安全控制模块,它主要有两部分内容:用户认证和用户权限管理。目前大致有三种安全模型:访问矩阵、基于角色的访问控制(RBAC-Role based access control)模型和多级模型。其中基于角色的访问控制模型得到了日益广泛的应用。
RBAC是目前公认的解决大型企业的统一资源访问控制的有效方法。其显著的两大特征是:一是减小授权管理的复杂性,降低管理开销;二是灵活地支持企业的安全策略,并对企业的变化有很大的伸缩性。
资源是应用系统中被管理、控制的对象,资源是权限管理的最小单位,资源的抽象要结合实际的需要确定粒度大小。
权限是对具体资源的访问许可。权限和资源密不可分,在这里,权限可以用一个二元组来表示(R,A),其中,R表示资源,A表示访问方式。
角色是指一个组织或任务中的工作或位置,它代表了一种资格、权利和责任。
用户就是一个可以独立访问应用系统中的资源的主体。用户在一般情况下是指应用系的使用者。
RBAC中只对角色分配资源的访问权限,从另一个角度说,角色是权限的某种组合。用户可以具有一个或多个角色,但不能直接对用户分配权限。角色的权限相对稳定,而用户容易变化,RBAC通过角色实现用户与权限的分离,增加了权限分配和管理的方便性和灵活性。
以上是RBAC的基本概念,下面结合Windows .Net Framework平台,给出一套简洁、实用的RBAC权限管理系统的设计方案。
Type位于.Type实际上是一个抽象基类,它有与每一种数据类型相对应的派生类。通过运行时获取Type派生类的实例,可能获取相应数据类型的所有信息。
传统编程语言如 C++,都提供了关键字(如 public 、private等)。这些关键字提供有关类成员的附加信息,还通过描述类成员对其他类的可访问性来进一步定义类成员的行为。由于编译器被显式设计为识别预定义关键字,编程者无法创建自己的关键字。
但在.Net Framework中,公共语言运行库CLR(Common Language Library )允许编程者添加类似关键字的描述性声明(称为属性)来批注编程元素,如类型、字段、方法和属性等。
编程者可以声明从 System.Attribute 派生的自定义属性类,用来存储特定的描述信息。
各个通常的应用软件系统中,除了需进行安全访问控制的资源各不相同外,其它如用户及角色的管理,角色的权限分配等基本相同,如果能对不同应用系统的资源抽象出相同的描述和访问接口,自然就能实现一套通用的权限管理系统。
系统的基本设计目标是,通过统一定义的应用系统资源树接口定义,实现应用系统无关的通用RBAC管理系统,如图1所示,应用系统通过统一定义的资源及其访问方式接口与权限管理系统平台进行交互。
本系统主要有以下功能:
Ø 用户管理:用户的编辑、角色分配及用户认证等;
Ø 角色管理:角色的编辑、权限分配等;
Ø 资源及权限管理:应用系统资源及访问方式以及权限的定义等;
Ø 安全访问控制:判别登录用户是否具备对特定资源的访问权限。
资源接口 |
权限管理系统 |
权限 分配 |
角色 分配 |
角色管理 |
用户管理 |
资源与权限管理 |
应用系统 |
图1 权限管理平台体系结构
资源是对应用系统中要进行安全访问控制的对象的抽象。依据应用对象类别的不同,资源也相应分为不同的资源类。
本系统设计采用64位的资源ID(ResourceID)来唯一标示系统的一个资源对象。应用系统需自定义一套完整的资源ID编码规则,对要安全访问控制的每一个对象,根据编码规则可得出一个资源ID。资源ID推荐采用分层设计,如可分为三个层次:应用模块ID-对象类别ID-对象ID。
由于可由应用系统对象得到相应的资源ID,本系统的数据库中不再需要单独建立资源与应用系统对象的映射表,这是本系统设计的一个创新之处。
用户对系统的不同资源通常有特定的访问方式,如对文件的访问方式有“读”、“写”、“执行”等。这里将对资源访问方式设计为可以按位组合的枚举量([FlagsAttribute]标示),基本数据类型为32位整数,即对一种资源总共可表示32种不同的访问方式。每个枚举值还带有自定义的属性(Attributes)。以下是文件的访问方式枚举量定义的示例代码(C#):
[FlagsAttribute]
public Enum File_AccessMode
{
[DisNameAttribute(“读”)]
Read = 0x01,
[DisNameAttribute(“写”)]
Write = 0x02,
[DisNameAttribute(“执行”)]
Execute,
}
由于访问方式可以按位组合,组合访问方式的表示被大大简化。如对文件的“读”与“写”的组合访问方式可以简记为:
File_AccessMode m=
File_AccessMode.Read | File_AccessMode.Write;
自定义属性“DisNameAttribute”给出枚举值的显示名称,示例定义参见下面的代码(C#):
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class DisNameAttribute : Attribute
{
public DisNameAttribute(string name)
{
this.name = name;
}
private string name;
public string Name
{
get { return name; }
}
}
不同应用系统需在代码中自定义各自系统内所有资源类别的访问方式枚举类型,本系统的数据库同样不需定义和存储各类资源访问方式表,这是本系统简化设计的核心。
为了统一对各个不同应用系统资源的访问,本系统采用分层组织的树形结构来描述应用系统的资源,UML类视图如图2所示。
图2 应用系统资源及访问方式接口定义
其中类ResourceTree为资源树,代表应用系统所有资源的集合,它包含ResourceNode的链表Nodes; 类ResourceNode是资源树的节点,代表一个具体的资源,ResourceNode同样可包含多个ResourceNode,ResourceNode的属性ID返回相应资源的ResourceID。
由于资源访问方式枚举量的定义各不相同,如何以统一的接口方式获取不同资源的访问方式是本平台设计的一个难点。这里采用属性AccessType统一返回资源访问方式枚举量的类型(Type)对象。通过下列代码可以得到访问方式枚举量的所有信息(C#):
Type t =resourceNode.AccessModeType;
FieldInfo[] fs=t.GetFields(BindingFlags.DeclaredOnly|
Binding Flags.Static|BindingFlags.Public);
int[] enumVals =new int[fs.Length];
string[] enumNames= new string[fs.Length];
int i =0;
foreach(FieldInfo f in fs)
{
enumVals[i]=f.GetValue(null);
DisNameAttribute[] ds=f.GetCustomAttribute(typeof(DisNameAttribute),false);
If(ds.Length != 0)
enumNames[I]=ds[0].Name;
}
上述代码中,enumVals数组中存储了所有访问方式的枚举值,enumNames数据组中存储了各个访问方式的显示用名称。
权限是指用户对具体资源的访问许可,权限和资源密不可分。这里权限用一个二元组来表示:
Permission(Resource,AccessMode)
其中Resource表示一个具体资源,AccessMode是用户对此资源的所授权的访问方式。需注意的是,由于AccessMode设计成可按位组合,所以此二元组表示了用户对一个资源的所有访问权限。
角色可由系统管理员或授权用户灵活定制。角色具有唯一且不重用的ID。
角色之间采用组合关系,一个角色可以包含其它多个角色,一个角色的权限是它本身及其所包含的其它角色所拥有的权限的集合。
Role_Table
字段 | 类型 | 描述 |
ID | int | 主键 |
Name | string | 名称 |
Status | int | 状态 |
… | … | … |
角色的所有相关信息均记录到数据库中的角色表Role_Table。
权限分配是指为角色配置某种权限。可以用三元组(Role,Resource,AccessMode)表示,即Role角色对Resource资源可以进行AccessMode的操作。
RolePermission_Table
字段 | 类型 | 描述 |
RoleID | int | 外键 |
ResourceID | Int64 | 外键 |
AccessMode | int | 访问方式 |
… | … | … |
角色的所有授权信息均存储到角色权限关联表RolePerssion_Table。
用户可由系统管理员或授权用户灵活增删。用户具有唯一且不重用的ID。
各个用户相互独立,不存在继承或组合关系。
User_Table
字段 | 类型 | 描述 |
ID | int | 主键 |
Name | string | 名称 |
Password | string | 加密口令 |
Status | int | 状态 |
… | … | … |
用户的所有相关信息均记录到数据库中的用户表User_Table。
角色委派是指为用户分配若干种角色。可以用二元组(User,Role)表示,含义是User用户属于角色Role。一个用户可以属于多个角色。
UserRole_Table
字段 | 类型 | 描述 |
Role_ID | int | 外键 |
User_ID | int | 外键 |
Status | int | 状态 |
… | … | … |
用户与角色的所有关联信息均记录到数据库的用户角色关联表UserRole_Table。
使用应用系统的用户首先要进行用户登录,登录成功后,结合UserRole_Table及RolePerssion_Table查询当前用户对所有资源的访问权限,根据返回结果在动态生成此用户对资源的所有权限表:
UserPermission_Table
字段 | 类型 | 描述 |
ResourceID | int64 | 资源 |
AccessMode | int | 访问方式 |
… | … | … |
其中AccessMode的值是用户所属的多个角色对某一资源的所有访问方式的组合。
当用户要对一个需安全访问控制的对象操作时,首先根据应用系统自定义的资源ID编码规则及访问对象的相关信息生成ResourceID,和应用系统定义的对此对象进行操作所需的访问权限accessMode,再查找UserPermission_Table表,判别当前用户是否具有相应的操作权限。
本文结合.Net Framework开发平台提供的新特性,给出了一套基于RBAC通用的普通应用系统权限管理的设计方案,本设计结构简洁、实用,并有较高的灵活性,满足普通应用系统对安全访问控制的需要。
参考文献:
[1] Sandhu R. ,Coyne E. J . ,Feinstein H. L. et al . Role - Based access control models[J ] . IEEE Computer ,1996 ,29 (2) :38 - 47.
[2] 汤鹏翔,一种实用的基于角色访问控制系统设计与实现。计算机应用,2002.22(12):41-43
[3] Julian Fempleman, David Vitter. Visual Studio .Net Framework Black Book[M]. 北京:水利出版社, 2003.