资源描述
今天在学习RBAC的时候在网上查了一些资料,本来想保存一个地址的,但是怕将来地址打不开,所以就复制过来吧,如有侵权之处,你来信告之,我会在第一时间删除!
RBAC初学笔记
什么是RBAC?
RBAC就是Role-Based Access Control,基于角色的访问控制。角色访问控制(RBAC)引入了Role的概念,目的是为了隔离User(即动作主体,Subject)与Privilege(权限,表示对Resource的一个操作,即Operation+Resource) ,更符合企业的用户、组织、数据和应用特征。
RBAC的关注点在于Role与user,Role与privilege的关系,也就是User Assignment与Permission Assignment的关系。
RBAC有以下优点:
1、 减少授权管理的复杂性,降低管理开销
2、 灵活的支持企业的安全策略,对企业的变化有很大的伸缩性
解决复杂的权限管理问题的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。
RBAC中的几个重要概念:
l Who:权限的拥有者或主体。典型的有Principal、User、Group、Role、Actor等等。跟授权有关系的实体就只有角色(Role)和用户(User)。譬如:业务经理(Role),张三(User)
Role:作为一个用户(User)与权限(Privilege)的代理层,解耦了权限和用户的关系,所有的授权应该给予Role而不是直接给User或Group。基于角色的访问控制方法的思想就是把对用户的授权分成两部份,用角色来充当用户行驶权限的中介。角色是一组访问权限的集合,一个用户可以是很多角色的成员,一个角色也可以有很多个权限,而一个权限也可以重复配置于多个角色。
User:用户就是一个可以独立访问计算机系统中的数据或者用数据表示的其它资源的主体,我们用USERS表示一个用户集合。用户在一般情况下是指人。
Group:是一组相关user的集合。User从group继承出来,也就具有了该group的角色权限。
个人觉得可以这么认为,role是抽象化了的user或group。
l What:权限针对的资源(Resource)(包括资源类别(the type of Resource)和资源实例(the instance of Resource))。譬如:报表。
粗粒度:表示类别级,即仅考虑对象的类别(the type of object),不考虑对象的某个特定实例。比如,用户管理中,创建、删除,对所有的用户都一视同仁,并不区分操作的具体对象实例。
细粒度:表示实例级,即需要考虑具体对象的实例(the instance of object),当然,细粒度是在考虑粗粒度的对象类别之后才再考虑特定实例。比如,合同管理中,列表、删除,需要区分该合同实例是否为当前用户所创建。
l How:亦作action,表示某种访问方法(亦请参考Operator条目解释)。譬如:删除。
l Operator:操作。表示施加于What的How动作。是一种Resource Related的概念,单独的How动作是没有实际意义的,譬如:删除;只有与具体资源结合在一起才有意义,譬如:删除报表。
下面的图展示了user,group,role,how的关系
权限系统的核心由以下三部分构成:
1. 创造权限
2. 分配权限
3. 使用权限
系统各部分的主要参与者对照如下:
1.创造权限 - Programer创造,
2.分配权限 - Administrator 分配,
3.使用权限 – User
1. Programer 向权限系统提供 Operator = Privilege + Resource
2. Administrator 利用 Operator 这个基本元素,来创造他理想中的权限模型。
如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联等等...
这些操作都是由 Administrator 来完成的.
3. User 使用 Administrator 分配给的权限去使用各个系统。
程序员只要回答一个问题,就是, 什么权限可以访问什么资源,也就是前面说的 Operator。程序员提供 Operator 就意味着给系统穿上了盔甲。Administrator 就可以按照他的意愿来建立他所希望的权限框架。Operator是这个系统中最关键的部分,它是一个纽带,一个系在Programmer,Administrator,User之间的纽带。(转自:http://www.1to2.us/RBAC-a156758.htm)
RBAC 模型初探
访问控制背景
访问控制技术是由美国国防部(Department of Defense, DoD)资助的研究和开发成果演变而来的。这一研究导致两种基本类型访问控制的产生:自主访问控制(Discretionary Access Control, DAC)和强制访问控制(Mandatory Access Control, MAC)。最初的研究和应用主要是为了防止机密信息被未经授权者访问,近期的应用主要是把这些策略应用到为商业领域。
自主访问控制,允许把访问控制权的授予和取消留给个体用户来判断。为没有访问控制权的个体用户授予和废除许可。自主访问控制机制允许用户被授权和
取 消访问其控制之下的任何客体(object),换句话说,用户就是他们控制下的客体的拥有者。然而,对于多数组织来说,最终用户对所访问的信息没有拥有 权。对于这些组织,公司或代理机构是事实上的系统客体和处理他们的程序的拥有者。访问优先权受组织控制,而且也常常基于雇员功能而不是数据所有权。
强制访问控制,在美国国防部 Trusted Computer Security Evaluation Criteria (TCSEC) 中定义如下:“一种限制访问客体的手段,它以包含在这些客体中的信息敏感性和访问这些敏感性信息的主体的正式授权信息(如清除)为基础”。
以上访问控制策略对于处理一些无需保密但又敏感的信息的政府和行业组织的需求并不是特别的适合。在这样的环境下,安全目标支持产生于现有法律、道德规范、 规章、或一般惯例的高端组织策略。这些环境通常需要控制个体行为的能力,而不仅仅是如何根据信息的敏感性为其设置标签从而访问这一信息的个人能力。
什么是基于角色访问控制(Role-Based Access Control, RBAC)?NIST 有如下定义。
访问是一种利用计算机资源去做某件事情的的能力,访问控制是一种手段,通过它这种能力在某些情况下被允许或者受限制(通常是通过物理上和基于系统的控 制)。基于计算机的访问控制不仅可规定是“谁”或某个操作有权使用特定系统资源,而且也能规定被允许的访问类型。这些控制方式可在计算机系统或者外部设备 中实现。
就基于角色访问控制而言,访问决策是基于角色的,个体用户是某个组织的一部分。用户具有指派的角色(比如医生、护士、出纳、经理)。定义角色的过程应该基于对组织运转的彻底分析,应该包括来自一个组织中更广范围用户的输入。
访问权按角色名分组,资源的使用受限于授权给假定关联角色的个体。例如,在一个医院系统中,医生角色可能包括进行诊断、开据处方、指示实验室化验等;而研究员的角色则被限制在收集用于研究的匿名临床信息工作上。
控制访问角色的运用可能是一种开发和加强企业特殊安全策略,进行安全管理过程流程化的有效手段。
用户(User)和角色(Role)
用户指访问系统中的资源的主体,一般为人,也可为 Agent 等智能程序。角色指应用领域内一种权力和责任的语义综合体,可以是一个抽象概念,也可以是对应于实际系统中的特定语义体,比如组织内部的职务等。针对角色 属性的不同,某些模型中将角色进一步细分为普通角色和管理员角色(可理解为全局角色)。
许可(Permissions)和权限(Permission)
许可描述了角色对计算机资源的访问和操作所具有的权限,其反映的是授权的结果。比如授予某个角色对计算机资源有读的权限,则代表了一个许可的存在,这个许 可表示:角色获取了对计算机资源的读许可。针对操作来说,其描述的是许可和操作之间的一种关联关系,而这层关系则表示了某一角色对某一操作所具有的权限及 权限状态。
角色和指派(Assignment)
指派包含两个方面,用户指派和许可指派。用户指派表示的是,将用户指派给特定的角色。许可指派表示的是为角色指派计算机资源的访问和操作许可。
会话(session)
会话表示的是用户和角色之间的关系。用户每次必须通过建立会话来激活角色,得到相应的访问权限。
角色和角色等级(Role Hierarchies)
角色本身仅仅只是一个名词,其本身并不能代表权限的大小。比如,我们可以定一个“Director”的角色,也可以定一个“Project Leader”的角色。对于现实中我们来说,看到这样两个角色,就清楚 DIR 的权限要比一个 PL 的权限级别高。但是对计算机来说,这两个角色仅仅是两个“词语”,是等同的。可以采用分等级角色,在角色上实现层次化来解决这些问题。也可以采用复合角色 (其表示的就是一个角色组的概念),对角色实现一定的分组和复合,以便于权限指派。在一些 OA 产品中经常出现分等级角色。
限制(Constraints)
模型中的职责分离关系(Separation of Duty),用于控制冲突(Conflict)。静态职责分离(Static SD)指定角色的互斥关系,用于用户指派阶段。避免同一用户拥有互斥的角色。实现简单,角色互斥语义关系清楚,便于管理不够灵活,不能处理某些实际情况。 动态职责分离(Dynamic SD)指定角色的互斥关系,用于角色激活阶段。允许同一用户拥有某些互斥的角色,但是不允许该用户同时激活互斥的角色。更灵活,直接与会话挂钩,适应实际 管理需要,实现复杂,不易管理。
利用 AOP 实现 .NET 上完整的基于角色的访问控制(RBAC)模型
作者:admin 日期:2006-11-30
一. 背景
1. .NET 平台上没有完整的 RBAC 机制,.NET 中的安全模型(代码访问安全性:CAS)只是实现到 Role 层次,没有细化到 Task 层次,ASP.NET 2.0 中的诸多安全机制,如 Membership、Web.Config 的安全配置,都只能针对 Role 进行设置,大家在利用这些安全机制,往往需要在程序/代码硬编码(HardCode)角色,这样就无法实现在运行期自定义角色的功能
2. Windows 2000/2003 中自带的 Authorization Manager 虽然实现了较为完整的RBAC模型,但一般只适用于 Windows 用户,而且也需要手动去进行权限检查(调用 AccessCheck方法)
3. 权限检查是一个通用操作,最好的实现方式就是面向方面的编程(AOP)
二、相关主题介绍
1. RBAC模型的要素:三个实体:用户、角色、任务(或操作)(User、Role、Task),其稳定性逐渐增强,两个关系,User<->Role、Role<->Task,其中:
o User 是日常管理运行时建立
o Role 是部署/交付建立
o Task 是开发时确定
o User<->Role 是日常管理运行时建立
o Role<->Task 是部署/交付时建立
2. 一般来说,Task是固定的,是和应用程序紧密绑定的,即使对之进行硬编码,也没有关系
3. User/Role 部分比较容易实现,例如ASP.NET 2.0中 Membership 的实现
三、具体实现
注:本文中实现 AOP 的思路主要来自于如下文章:Aspect oriented Programming using .NET - AOP in C# (http://www.developerfusion.co.uk/show/5307/3/) ,这是我看到的、在.NET 上实现 AOP最简捷/方便的方法,它不便提供了原理介绍,也提供了 Visual Studio 2005 的 Sample Project ,其中有 Security Check 和 Logging 的 AOP 功能。它的优点在于,在实现 AOP 的同时,不需要再去建立接口(这是很多人的做法),直接在原有类上进行少量改动,即可实现完整的 AOP 功能。
1. 定义描述“Task”(任务)的 Attribute
using System;
namespace BusinessLogic.Security
...{
/**////
/// 用于定义系统中的操作
///
[AttributeUsage(AttributeTargets.All,AllowMultiple=false,Inherited=true)]
public sealed class Task : Attribute
...{
private string _name,_description;
public string Name
...{
get ...{ return _name; }
set ...{ _name = value; }
}
public string Description
...{
get ...{ return _description; }
set ...{ _description = value; }
}
public Task(string name,string description)
...{
_name = name;
_description = description;
}
public Task()
...{
}
}
}
2. 编写权限检查的 AOP 类 SecurityAspect,完成权限检查的功能
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;
namespace BusinessLogic.Security
...{
//消息接收器
internal class SecurityAspect : IMessageSink
...{
//内部变量
private IMessageSink m_next;
//构造方法
internal SecurityAspect(IMessageSink next)
...{
m_next = next;
}
IMessageSink 实现#region IMessageSink 实现
public IMessageSink NextSink
...{
get ...{ return m_next; }
}
//同步处理消息
public IMessage SyncProcessMessage(IMessage msg)
...{
Preprocess(msg);
IMessage returnMethod = m_next.SyncProcessMessage(msg);
return returnMethod;
}
//异步处理消息(不实现)
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
...{
throw new InvalidOperationException();
}
#endregion
自定义的 AOP 方法#region 自定义的 AOP 方法
private void Preprocess(IMessage msg)
...{
//只处理方法调用
if (!(msg is IMethodMessage)) return;
//获取方法中定义的 Task 属性,交给权限检查类去检查
IMethodMessage call = msg as IMethodMessage;
MethodBase mb = call.MethodBase;
object[] attrObj = mb.GetCustomAttributes(typeof(Task), false);
if (attrObj != null)
...{
Task attr = (Task)attrObj[0];
if(!string.IsNullOrEmpty(attr.Name))
AzHelper.PermissionCheck(attr.Name);
}
// Type type = Type.GetType(call.TypeName);
}
#endregion
}
public class PermissionCheckProperty : IContextProperty, IContributeObjectSink
...{
IContributeObjectSink 实现,将 AOP 类加入消息处理链#region IContributeObjectSink 实现,将 AOP 类加入消息处理链
public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
...{
return new SecurityAspect(next);
}
#endregion
IContextProperty 实现#region IContextProperty 实现
public string Name
...{
get ...{ return "PermissionCheckProperty"; }
}
public void Freeze(Context newContext)
...{
}
public bool IsNewContextOK(Context newCtx)
...{
return true;
}
#endregion
}
//特性定义,用于 Consumer
[AttributeUsage(AttributeTargets.Class)]
public class PermissionCheckAttribute : ContextAttribute
...{
public PermissionCheckAttribute() : base("PermissionCheck") ...{ }
public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
...{
ccm.ContextProperties.Add(new PermissionCheckProperty());
}
}
}
?
3. 定义用于权限检查的两个类:AzMan、AzHelper
这两个类的功能是从 XML 配置文件中读入 Role 和 Task 的映射关系,以确定 Role 中是否包含 Task 的引用,从而确定当前 Role 是否具有对此 Task 的权限。
注:这里可根据项目的实际情况,如果你的 Role 和 Task 的映射关系是存放在 Windows 的授权管理器(Authorizatiom Manager)或数据库中,你可以使用自已
的方法来替换下列类。
在本例中,我的 Role 和 Task 的关系是存放在 XML 文件中,XML文件的格式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<ACL>
<Tasks>
<Task Name="AddItem" Description="增加" />
<Task Name="ModifyItem" Description="修改" />
<Task Name="RemoveItem" Description="删除" />
<Task Name="ListItem" Description="获取列表" />
</Tasks>
<Roles>
<Role Name="Manager">
<Task Name="AddItem" />
<Task Name="ModifyItem" />
<Task Name="RemoveItem" />
<Task Name="ListItem" />
</Role>
</Roles>
</ACL>
AzMan.cs 完成角色/任务映射关系的检查
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace BusinessLogic.Security
...{
public class AzMan
...{
public static bool AccessCheck(string taskName, string[] roles, XmlDocument aclDoc)
...{
XmlNode rootNode = aclDoc.DocumentElement;
XmlNodeList roleNodes,taskNodes;
bool IsPermissiable = false;
for (int i = 0; i < roles.Length; i++)
...{
roleNodes = rootNode.SelectNodes("Roles/Role[@Name='" + roles[i] + "']");
if (roleNodes != null)
...{
taskNodes = roleNodes.Item(0).SelectNodes("Task[@Name='" + taskName + "']");
if (taskNodes.Count != 0)
...{
IsPermissiable = true;
break;
}
}
}
return IsPermissiable;
}
}
}
AzHelper.cs 助手类,协助其他类,更好地调用 AzMan 类的方法,以及基于性能考虑,对Role<-->Task的XML配置文件进行缓存:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Web;
using System.Web.Security;
using System.Diagnostics;
using System.Reflection;
using System.Web.Caching;
namespace BusinessLogic.Security
...{
public class AzHelper
...{
/**////
/// 检查当前用户是否具有执行当前任务的权限,如果有权限,则不做任何处理
/// 如果不具有权限,则引发异常
///
public static void PermissionCheck(string taskName)
...{
if (HttpContext.Current != null)
...{
XmlDocument aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"];
if (aclDoc == null)
...{
CacheXml();
aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"];
}
string[] roles = Roles.GetRolesForUser();
if (!AzMan.AccessCheck(taskName, roles, aclDoc))
throw new UnauthorizedAccessException("访问被拒绝,当前用户不具有操作此功能的权限!");
}
}
/**////
/// 检查当前用户是否具有执行指定任务的权限
///
///
任务名称
/// True/False 是否允许执行
public static bool IsPermissible(string taskName)
...{
if (HttpContext.Current != null)
...{
XmlDocument aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"];
if (aclDoc == null)
...{
CacheXml();
aclDoc = (XmlDocument)HttpContext.Current.Cache["ACLDoc"];
}
string[] roles = Roles.GetRolesForUser();
aclDoc.Load(HttpContext.Current.Server.MapPath("~/App_Data/ACL.xml"));
return AzMan.AccessCheck(taskName, roles, aclDoc);
}
else return true;
}
/**////
/// 缓存 XML 文件
///
private static void CacheXml()
...{
string fileName = HttpContext.Current.Server.MapPath("~/App_Data/ACL.xml");
XmlDocument aclDoc = new XmlDocument();
aclDoc.Load(fileName);
HttpContext.Current.Cache.Insert("ACLDoc", aclDoc, new CacheDependency(fileName));
}
}
}
4. 业务逻辑类的实现
由于大多数工作都在 AOP 中实现了,所以业务逻辑类的实现较为简单,主要分为以下几个步骤:
· 在类的层次定义要求 AOP 方式权限检查的 Attribute: [PermissionCheck()]
·
· 使类继承自 ContextBoundObject 对象
·
· 在方法层次上利用 Task Attribute 来定义其对应的操作(注:多个方法可以定义为同一个 Task)
·
例如:ItemManager.cs
namespace BusinessLogic
...{
[PermissionCheck()]
public class ItemManager : ContextBoundObject
...{
[Task("AddItem","增加")]
public void AddItem(Item item)
...{
//...
}
}
}
这样就可以了,CLR 会在运行时检查类的 PermissionCheck?Attribute,然后寻找方法上的 Task ,取出当前用户对应的 Role ,再去进行匹配检查,如果不能执行此操作,会抛出 UnauthorizedAccessException 的异常,在外部进行处理即可(如在 ASP.NET 中增加 ErrorPage 等)
5. 其他相关功能的实现
Q:如果我写程序时,在各个业务逻辑类定义了大量的 Task ,如果统一提取出来?
A:利用反射可取出程序集中定义的所有 Task ,代码如下:
List<string> dic = new List<string>();
StringBuilder sXml = new StringBuilder("");
string curDir = this.GetCurrentPath();
Assembly ass = Assembly.LoadFile(curDir + "\\AppFramework.BusinessLogic.dll");
foreach (Type t in ass.GetTypes())
...{
MethodInfo[] mis = t.GetMethods();
foreach (MethodInfo mi in mis)
...{
object[] attrs = mi.GetCustomAttributes(false);
if (attrs.Length > 0)
...{
foreach (object attr in attrs)
...{
if (attr.GetType().ToString().IndexOf("Task") >= 0)
...{
Task ta = (Task)attr;
//检查重复的 Task
if (dic.IndexOf(t
展开阅读全文