AOP的特性使得它非常适合用来设计类似权限控制的功能,这是本文的基础,如果想要了解AOP的实现,可以参考《动态织入的AOP实现》。
在基于角色的访问控制(RBAC)中,有三要素:用户、角色、任务(或操作)(User、Role、Task),其稳定性逐渐增强,两个关系,User<->Role、Role<->Task,其中:
- User 是日常管理运行时建立
- Role 是部署/交付建立
- Task 是开发时确定
- User<->Role 是日常管理运行时建立
- Role<->Task 是部署/交付时建立
在本例中,针对Task和Role,我们设计如下的两个类:
[AttributeUsage(AttributeTargets.All, AllowMultiple =
false
, Inherited =
true
)]
public
class
TaskAttribute: Attribute
{
public
TaskAttribute(
string
taskName,
string
taskDescription)
{
TaskName = taskName;
TaskDescription = taskDescription;
}
public
string
TaskName {
get
;
set
; }
public
string
TaskDescription {
get
;
set
; }
}
public
class
Role
{
public
string
Name {
get
;
set
; }
public
List<TaskAttribute> Tasks {
get
;
set
; }
}
|
可以看到,Task是继承自Attribute的,源于Task需要和实际的功能接口匹配起来,而Role,则无此需要。
本文演示所需要的权限关系描述如下:
1:系统有4个权限;
2:系统有两个角色,一个叫做Manager,它具有两个权限,另一个角色为Common,它当前不具备任何权限;
以上的关系描述,我们在代码当中模拟如下:
//模拟系统总共有4种权限
public
static
List<TaskAttribute> Tasks
{
get
{
if
(_tasks ==
null
)
{
_tasks =
new
List<TaskAttribute>()
{
new
TaskAttribute(
"AddItem"
,
"增加"
),
new
TaskAttribute(
"ModifyItem"
,
"修改"
),
new
TaskAttribute(
"RemoveItem"
,
"删除"
),
new
TaskAttribute(
"ListItem"
,
"获取列表"
)
};
}
return
_tasks;
}
}
private
static
List<Role> _roles;
//模拟系统总共有两类角色
//第一类角色Manager,有增加和修改权限
//第二类角色Common,没有任何权限
public
static
List<Role> Roles
{
get
{
if
(_roles ==
null
)
{
_roles =
new
List<Role>()
{
new
Role(){Name =
"Manager"
, Tasks =
new
List<TaskAttribute>()
{
new
TaskAttribute(
"AddItem"
,
"增加"
),
new
TaskAttribute(
"ModifyItem"
,
"修改"
)
}},
new
Role(){Name =
"Common"
, Tasks =
new
List<TaskAttribute>()}
};
}
return
_roles;
}
}
|
权限判断在切面部分,简化如下(可以看到是判断当前用户是否具有相关权限):
public
class
AuthorityHandler : ICallHandler
{
/// <summary>
/// Invoke order
/// </summary>
public
int
Order {
get
;
set
; }
public
IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
MethodBase mb = input.MethodBase;
object
[] attrObj = mb.GetCustomAttributes(
typeof
(TaskAttribute),
false
);
if
(attrObj ==
null
)
{
throw
new
ArgumentException(
"TaskAttribute should be defined with the AuthorityAttribute"
);
}
else
{
TaskAttribute attr = (TaskAttribute)attrObj[0];
if
(!
string
.IsNullOrEmpty(attr.TaskName))
{
string
taskName = attr.TaskName;
//get current user's roles
IEnumerable<Role> currentUserRoles =
from
p
in
SampleApp.Roles
where
p.Name == SampleApp.User.Name
select
p;
//if match then return;
foreach
(Role currentUserRole
in
currentUserRoles)
{
IEnumerable<TaskAttribute> tasks =
from
p
in
currentUserRole.Tasks
where
p.TaskName == taskName
select
p;
if
(tasks.Count() > 0)
{
var
retvalue = getNext()(input, getNext);
return
retvalue;
}
}
//else throw exception
throw
new
UnauthorizedAccessException(
"access denied"
);
}
}
return
null
;
}
}
public
class
AuthorityAttribute : HandlerAttribute
{
public
override
ICallHandler CreateHandler(IUnityContainer container)
{
return
new
AuthorityHandler();
}
}
|
调用方代码:
static
void
Main() {
var
container1 =
new
UnityContainer()
.AddNewExtension<Interception>()
.RegisterType<IBiz, Biz1>();
container1
.Configure<Interception>()
.SetInterceptorFor<IBiz>(
new
InterfaceInterceptor());
SampleApp.User =
new
User() { Name =
"Common"
};
var
sample1 = container1.Resolve<IBiz>();
sample1.AddItem();
Console.ReadKey();
}
|
可以看到,使用了Unity来进行AOP;
运行效果:
本文转自最课程陆敏技博客园博客,原文链接:http://www.cnblogs.com/luminji/archive/2012/01/13/2321896.html,如需转载请自行联系原作者