標籤:des style blog http strong 資料
續接上篇:Asp.Net MVC 許可權控制(二):Controller層級控制
再次在重構!這次對Controller和Action進行驗證。
思路:系統有很多功能集,功能集對應很多Controller和Action,角色指派很多功能集。
首先構建一個基礎資料:
1.功能集初始化:
/// <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