MVC AuthorizeAttribute 动态授权

开发中经常会遇到权限功能的设计,而在MVC 下我们便可以使用重写 AuthorizeAttribute 类来实现自定义的权限认证

首先我们的了解 AuthorizeAttribute 下面3个主要的方法

AuthorizeCore,HandleUnauthorizedRequest,OnAuthorization

一般情况下我们不需要去重 OnAuthorization  方法

主要是 AuthorizeCore,HandleUnauthorizedRequest 两个方法

HandleUnauthorizedRequest 是用来响应认证失败后的处理

AuthorizeCore 方法则是授权方法

 由于我是用OWIN 去认证的 所以只需要重写AuthorizeCore 方法

创建一个接口 具体作用后面会说到

interface IAuthorize { }

模块实体信息,用于存放一些模块附加信息,为选择权限页面提供数据

 public class ModuleEntity
    {
        private Type _type;
    
        private MyModuleAttribute _m;
        public MyModuleAttribute Module { get{return this._m;}  }
        List<AuthorizeEntity> _authorizes;
        private ModuleEntity() { }
        public static ModuleEntity Create(MyModuleAttribute m, Type type)
        {
            ModuleEntity model = new ModuleEntity();
            model._type = type;
            model._m = m;
            return model;
        }
        public static  void IterateAction( ModuleEntity entity)
        {
                     //反射模块下的所有权限信息 
        }
    }

 

操作枚举表示需要授权方法的行为

public enum AuthorizeAction : uint
    {
        Empty=0,
        List = 1,
        Look = 2,
        Add = 3,
        Editor = 4,
        Delete = 5,
    }

 

 

权限实体信息 同模块实体信息一样 为权限页面提供数据

public class AuthorizeEntity
    {
        private AuthorizeAction _action;
        private string _name;
        public AuthorizeAction Action { get { return this._action; } }
        public string Name { get { return this._name; } }
        public AuthorizeEntity(AuthorizeAction a, string name)
        {
            this._action = a;
            this._name = name;
        }
    }

 

 建立一个 MyModuleAttribute 给 Controllers 标记一些附加信息,主要为后面反射出 ModuleEntity

public class MyModuleAttribute : System.Attribute
    {
        readonly MyModule ID;
        readonly string NAME;
        public MyModuleAttribute(MyModule id, string name)
        {
            this.ID = id;
            this.NAME = name;
        }
        public MyModule Id { get { return this.ID; } }
        public string Name { get { return this.NAME; } }

    }

 

最后就是要建一个最主要的类 MyAuthorizeAttribute 我们需要重写AuthorizeAttribute 基类下的AuthorizeCore 方法已满足我们的权限要求,

public class MyAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        readonly string NAME;
        readonly AuthorizeAction ACTION;
        readonly MyModule MYMODULE;
        public AuthorizeAction Action { get { return this.ACTION; } }
        public string Name { get { return this.NAME; } }
        public MyModule MyModule { get { return MYMODULE; } }
        public MyAuthorizeAttribute(MyModule module,string name, AuthorizeAction action)
            : base()
        {
            this.MYMODULE = module;
            this.NAME = name;
            this.ACTION = action;
        }
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.User.Identity.IsAuthenticated)
                return false;
            var Identity = (System.Security.Claims.ClaimsIdentity)HttpContext.Current.User.Identity;
            if (Identity.RoleClaimType  != RoleType.System.ToString())
            {
                var v = string.Format("{0}.{1}",(int) this.MYMODULE,(int)ACTION) ;
                 foreach(var v1 in UserTicket.GetInstance().GetAuthorize(Identity.Name))
                 {
                     if (v == v1)
                     {
                         return true;
                     }
                 }
                 HttpContext.Current.Response.Redirect("/Error/Index");
            }
            return true;
        }

现在方法已经建立好了,那这些方法怎么使用呢,我们在重新回到最开始的 IAuthorize 接口来说起

IAuthorize 接口是一个空的接口没有任何的实现方法,其实他的目的主要是为了 在程序运行时候反射出所有需要进行授权认证的 Controller

public class DefaultController : Controller, IAuthorize
{
    public class ActionResult Index()
{
  return view()
}
}

 这样就我们就可以在程序启动的时候通过反射当前程序集下 所有继承 IAuthorize 接口的Controller

 当仅仅这样还是不够的 我们可以看到 AuthorizeCore 方法下面 有一个比较操作,值是通过两个枚举拼接的,一个是行为 一个是模块

 我们要为 Controller 添加模块信息 ,使用定义的MyModuleAttribute 类,在为Controller下具体的功能函数添加授权属性MyAuthorize ,被标记的方法就需要进行权限比较了

[MyModule(MyModule.Main , "主模块")]
    public class DefaultController : Controller, IAuthorize
    {
        [MyAuthorize( MyModule.Main,"首页", AuthorizeAction.List)]
        public ActionResult Index()
        {
            return View();
        }
 
    }

  这样一个动态的AuthorizeAttribute授权就完成了,但是也会有疑问 这里的MyModule 好像并没有什么太大的作用啊 ,

  这里主要的权限验证 就是 MyAuthorize 类 ,MyModule 只是为了为页面提供数据,这样我们就无需将模块信息存到数据库中去了

 

posted @ 2016-05-31 22:30  zhengdi  阅读(426)  评论(0)    收藏  举报