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;
運作效果:

代碼下載下傳:
權限.rar本文基于
Creative Commons Attribution 2.5 China Mainland License釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名
http://www.cnblogs.com/luminji(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。