通过MVC的AuthorizeAttribute来进行权限验证
随着使用项目人数的不断庞大,各种权限控制一定要完善.
下面就简单介绍一种MVC进行权限控制的方法
MSDN地址:https://msdn.microsoft.com/zh-cn/library/system.web.mvc.authorizeattribute_methods(v=vs.118).aspx
1 /// <summary> 通行证登录验证过滤器</summary> 2 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 3 public class CheckLoginFilter : AuthorizeAttribute 4 { 5 /// <summary>公用,不需要登录即可访问,如登录页面</summary> 6 public const string PublicRole = "1"; 7 /// <summary>要登录才可以访问</summary> 8 public const string LoginRole = "2"; 9 static MenuResponseModel GetMenuResponseModel(AuthorizationContext filterContext) 10 { 11 if (filterContext.HttpContext.Session != null) 12 { 13 if (filterContext.HttpContext.Session["MenuAndUserInfo"] == null) 14 { 15 //获得菜单的数据 16 string[] userNameAndPassWord = 17 ((FormsIdentity)filterContext.HttpContext.User.Identity).Ticket.UserData.Split('|'); 18 if (userNameAndPassWord.Length > 1) 19 filterContext.HttpContext.Session["MenuAndUserInfo"] = 20 new MenuService().GetMenuAndUserInfo(userNameAndPassWord[0], userNameAndPassWord[1]); 21 } 22 return (MenuResponseModel)filterContext.HttpContext.Session["MenuAndUserInfo"]; 23 } 24 return new MenuResponseModel(); 25 } 26 /// <summary>重定向或显示信息</summary> 27 static void RedirectOrShow(AuthorizationContext filterContext, string redirectUrl, string message) 28 { 29 if (filterContext.HttpContext.Request.IsAjaxRequest()) //如果是Ajax提交 30 { 31 filterContext.HttpContext.Response.Write(message); 32 } 33 else 34 { 35 filterContext.HttpContext.Response.Redirect(redirectUrl 36 + (redirectUrl.IndexOf('?')>0?"&":"?") + "message=" +filterContext.HttpContext.Server.UrlEncode(message)); 37 } 38 filterContext.HttpContext.Response.End(); 39 filterContext.Result = new EmptyResult();//返回一个空结果,不然页面会继续执行 40 } 41 /// <summary>验证登录</summary> 42 public override void OnAuthorization(AuthorizationContext filterContext) 43 { 44 List<string> roles = Roles.Split(',').ToList(); 45 if (filterContext.HttpContext.User.Identity.IsAuthenticated) 46 { 47 MenuResponseModel userInfoAndMenu = GetMenuResponseModel(filterContext); 48 if (roles.Contains(PublicRole)||roles.Contains(LoginRole)) return; 49 if (userInfoAndMenu.MenuUrl.ContainsKey(MenuService.GetMenuUrl(filterContext.HttpContext.Request.RawUrl))) return; 50 RedirectOrShow(filterContext, "/gnselftrip/Home/Error", "原地址:" + filterContext.HttpContext.Request.RawUrl 51 + "\r\n解析后:" + MenuService.GetMenuUrl(filterContext.HttpContext.Request.RawUrl) + "没有权限"); 52 } 53 else if (filterContext.HttpContext.Request.Url != null)//获取返回页面url 54 { 55 if (roles.Contains(PublicRole)) return; 56 string redirectUrl = "/gnselftrip/Home/Login?ReturnUrl="//原来为FormsAuthentication.LoginUrl 57 +filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.Url.AbsoluteUri); 58 RedirectOrShow(filterContext, redirectUrl, "请登录!"); 59 } 60 }
这样,偶们的filter就写好了
具体使用时,先来个基类
1 [CheckLoginFilter] 2 public class AdminControllerBase : Controller 3 { 4 //do sth 5 }
然后具体的控制器继承该基类
1 public class DemoController : AdminControllerBase 2 { 3 [CheckLoginFilter(Roles = CheckLoginFilter.LoginRole)] 4 public ActionResult TestLogin() 5 { 6 return View();//此时只有登录的人才能访问此视图 7 } 8 [CheckLoginFilter(Roles = CheckLoginFilter.PublicRole)] 9 public ActionResult TestWithVisitor() 10 { 11 return View();//此时任何人都可以访问此视图 12 } 13 public ActionResult TestPointerRole() 14 { 15 return View();//此时必须登录人权限中指定了此视图才可以访问 16 } 17 }
这样用实际上和使用ActionFilterAttribute来说没有什么区别(具体见MVC 过滤器 构建会员是否登录)
好处就是,我能够在我自定义的基类中继续打标签AccountFilterAttribute,来真正处理OnActionExecuting及OnActionExecuted的重写的操作(其实直接在基类里面重写都行的),使得代码不会太乱0.0