zoukankan      html  css  js  c++  java
  • 基于Unity的AOP的符合基于角色的访问控制(RBAC)模型的通用权限设计

    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;

    运行效果:

    image

    代码下载:权限.rar

  • 相关阅读:
    一篇文章搞懂密码学基础及SSL/TLS协议
    如何编写一个多进程性能测试程序
    自动化测试用例编写日志总结(一)
    Python lambda匿名函数
    Python map() 函数
    python中sorted函数的理解(对list列表排序,对dict字典排序)
    python list列表冒泡排序
    range的用法
    同时安装python2和python3是使用pip的方法:
    cmd输出文件树结构
  • 原文地址:https://www.cnblogs.com/luminji/p/2321896.html
Copyright © 2011-2022 走看看