续接上篇:Asp.Net MVC 权限控制(二):Controller级别控制
再次在重构!这次对Controller和Action进行验证。
思路:系统有很多功能集,功能集对应很多Controller和Action,角色分配很多功能集。
首先构建一个基础数据:
1.功能集初始化:
class="brush:csharp;gutter:true;"> /// <summary> /// 系统模块 /// </summary> public class SystemModule { public SystemModule() { this.ID = Guid.NewGuid(); } public Guid ID { get; set; } public string Name { get; set; } public string Description { get; set; } public SystemModule Parent { get; set; } public List<SystemModuleController> SystemModuleControllers { get; set; } public static List<SystemModule> Init() { var m1 = new SystemModule { Name = "资源监测" }; var m2 = new SystemModule { Name = "规划管理" }; var c1 = new SystemModuleController { ControllerName = "PlanManagement", ActionName = "Search" }; var c2 = new SystemModuleController { ControllerName = "PlanManagement", ActionName = "Add" }; var c3 = new SystemModuleController { ControllerName = "PlanManagement", ActionName = "Edit" }; var c4 = new SystemModuleController { ControllerName = "PlanManagement", ActionName = "Delete" }; var c5 = new SystemModuleController { ControllerName = "PlanManagement", ActionName = "Approval" }; var m21 = new SystemModule { Name = "规划信息查询", Parent = m2, SystemModuleControllers = new List<SystemModuleController> { c1 } }; var m22 = new SystemModule { Name = "规划信息管理", Parent = m2, SystemModuleControllers = new List<SystemModuleController> { c2, c3, c4 } }; var m23 = new SystemModule { Name = "规划辅助审批", Parent = m2, SystemModuleControllers = new List<SystemModuleController> { c5 } }; return new List<SystemModule> { m1, m2, m12, m21, m22, m23 }; } }
2.角色初始化:
/// <summary> /// 角色 /// </summary> public class SystemRole { public SystemRole() { this.ID = Guid.NewGuid(); } public Guid ID { get; set; } public string Name { get; set; } public string Description { get; set; } public List<SystemModule> SystemModules { get; set; } public static SystemRole Init(string[] roles) { var modules = SystemModule.Init(); var systemModules = roles.Select(r => modules.FirstOrDefault(m => m.Name == r)).ToList(); var role = new SystemRole { Name = "默认角色", SystemModules = systemModules }; return role; } }
3. 系统所有Controller和Action的读取
/// <summary> /// 读取系统的所有Controller和Action /// </summary> public class SystemModuleController { public SystemModuleController() { this.ID = Guid.NewGuid(); } public Guid ID { get; set; } public string ModuleName { get; set; } public string ControllerName { get; set; } public string ActionName { get; set; } public string Description { get; set; } public List<SystemModuleController> SystemModuleActions { get; set; } public static List<SystemModuleController> GetSystemModuleController() { var systemModuleControllers = new List<SystemModuleController>(); // 读取项目中的Controller var types = Assembly.Load("PRMMS.Authorization").GetTypes().Where(b => b.BaseType != null && b.BaseType.Name == "BaseController"); foreach (var type in types) { // 标记需要权限验证的Controller var modules = type.GetCustomAttributes(typeof(ModuleAuthorizationAttribute), true); if (modules.Length == 1) { // Controller名称 var controllerName = type.Name.Replace("Controller", ""); // Controller描述 var description = string.Empty; var attrs = type.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), true); if (attrs.Length > 0) { description = (attrs[0] as System.ComponentModel.DescriptionAttribute).Description; } // 获取Controller下的Action var systemModuleControllerAction = new List<SystemModuleController>(); var actions = type.GetMethods().Where(a => a.ReturnType != null && a.ReturnType.Name == "ActionResult"); foreach (var action in actions) { // Action名称 var actionName = action.Name; // Action描述 var desc = string.Empty; var act = action.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), true); if (act.Length > 0) { desc = (act[0] as System.ComponentModel.DescriptionAttribute).Description; } systemModuleControllerAction.Add(new SystemModuleController { ControllerName = controllerName, ActionName = actionName, Description = desc }); } var systemModule = new SystemModuleController { ControllerName = controllerName, Description = description, SystemModuleActions = systemModuleControllerAction }; systemModuleControllers.Add(systemModule); } } return systemModuleControllers; } }
系统登录后,初始化权限并保存缓存中。
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Login(LoginModel model, string returnUrl) { var userName = model.UserName; FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket( 1, userName, DateTime.Now, DateTime.Now.AddMinutes(20), false, model.Roles.Aggregate((i, j) => i + "," + j) ); string encryptedTicket = FormsAuthentication.Encrypt(authTicket); var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); System.Web.HttpContext.Current.Response.Cookies.Add(authCookie); // 初始化权限 var systemRole = SystemRole.Init(model.Roles); // 缓存权限 AccountHelper.AddCache(systemRole.SystemModules); return RedirectToAction("Index", "Home"); }
AccountHelper:
public class AccountHelper { private const string CacheName = "SystemModules"; /// <summary> /// 获取用户信息 /// </summary> /// <returns></returns> public static FormsAuthenticationTicket GetCookieUser() { HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie == null || authCookie.Value == "") { return null; } try { return FormsAuthentication.Decrypt(authCookie.Value); } catch (Exception ex) { return null; } } /// <summary> /// 添加缓存 /// </summary> /// <param name="systemModules"></param> public static void AddCache(List<SystemModule> systemModules) { HttpContext.Current.Cache[CacheName] = systemModules; } /// <summary> /// 读取缓存 /// </summary> /// <returns></returns> public static List<SystemModule> GetCache() { if (HttpContext.Current.Cache[CacheName] == null) { // 重新构建权限 var user = GetCookieUser(); var roles = user.UserData.Split(new[] { ',' }); HttpContext.Current.Cache[CacheName] = SystemRole.Init(roles).SystemModules; } return (List<SystemModule>)HttpContext.Current.Cache[CacheName]; } /// <summary> /// 验证Controller和Action /// </summary> /// <param name="controllerName"></param> /// <param name="actionName"></param> /// <returns></returns> public static bool ValidatePermission(string controllerName, string actionName) { var systemModules = GetCache(); foreach (var systemModule in systemModules) { if (systemModule != null && systemModule.SystemModuleControllers != null) { foreach (var controller in systemModule.SystemModuleControllers) { if (controller.ControllerName == controllerName && controller.ActionName == actionName) return true; } } } return false; } }
同样在业务的Controller添加拦截标记
[LoginAllow] [PermissionFilter] public class BaseController : Controller { } [Description("规划管理控制器")] [ModuleAuthorization] public class PlanManagementController : BaseController { [Description("首页")] public ActionResult Index() { return View(); } [Description("查询")] public ActionResult Search() { return View(); } [Description("添加")] public ActionResult Add() { return View(); } [Description("编辑")] public ActionResult Edit() { return View(); } [Description("删除")] public ActionResult Delete() { return View(); } [Description("审批")] public ActionResult Approval() { return View(); } }
拦截器:PermissionFilterAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class PermissionFilterAttribute : ActionFilterAttribute { // OnActionExecuted 在执行操作方法后由 ASP.NET MVC 框架调用。 // OnActionExecuting 在执行操作方法之前由 ASP.NET MVC 框架调用。 // OnResultExecuted 在执行操作结果后由 ASP.NET MVC 框架调用。 // OnResultExecuting 在执行操作结果之前由 ASP.NET MVC 框架调用。 /// <summary> /// 在执行操作方法之前由 ASP.NET MVC 框架调用。 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { //fcinfo = new filterContextInfo(filterContext); //根据验证判断进行处理 if (!this.AuthorizeCore(filterContext)) { filterContext.RequestContext.HttpContext.Response.Redirect("~/Account/Login"); } } /// <summary> /// //权限判断业务逻辑 /// </summary> /// <param name="filterContext"></param> /// <returns></returns> protected virtual bool AuthorizeCore(ActionExecutingContext filterContext) { object[] filter; // 验证当前Action是否是匿名访问Action filter = filterContext.Controller.GetType().GetCustomAttributes(typeof(AnonymousAttribute), true); if (filter.Length == 1) { return true; } // 验证当前Action是否是权限控制页面Action filter = filterContext.Controller.GetType().GetCustomAttributes(typeof(ModuleAuthorizationAttribute), true); if (filter.Length == 1) { //获取 controllerName 名称 var controllerName = filterContext.RouteData.Values["controller"].ToString(); //获取ACTION 名称 var actionName = filterContext.RouteData.Values["action"].ToString(); return AccountHelper.ValidatePermission(controllerName, actionName); } // 验证当前Action是否是登录用户Action filter = filterContext.Controller.GetType().GetCustomAttributes(typeof(LoginAllowAttribute), true); if (filter.Length == 1) { return HttpContext.Current.User.Identity.IsAuthenticated; } throw new Exception("用户验证失败!"); } }
代码下载:PRMMS.Authorization.zip