基于Unity的AOP的符合基于角色的访问控制(RBAC)模型的通用权限设计

AOP的特性使得它非常适合用来设计类似权限控制的功能,这是本文的基础,如果想要了解AOP的实现,可以参考《动态织入的AOP实现》。

在基于角色的访问控制(RBAC)中,有三要素:用户、角色、任务(或操作)(User、Role、Task),其稳定性逐渐增强,两个关系,User<->Role、Role<->Task,其中:

  • User 是日常管理运行时建立
  • Role 是部署/交付建立
  • Task 是开发时确定
  • User<->Role 是日常管理运行时建立
  • Role<->Task 是部署/交付时建立

在本例中,针对Task和Role,我们设计如下的两个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[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,它当前不具备任何权限;

以上的关系描述,我们在代码当中模拟如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//模拟系统总共有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;
    }
}

权限判断在切面部分,简化如下(可以看到是判断当前用户是否具有相关权限):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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();
    }
}

调用方代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;

运行效果:

image

代码下载:权限.rar

posted @   陆敏技  阅读(3970)  评论(3编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
Web Counter
Coupon for Contacts
点击右上角即可分享
微信分享提示