今天把用戶的菜單顯示和頁面的按鈕顯示都做好了,下面先來個效果圖

接下來說下我實現的方法:
首先我在每個方法前面都加了這個屬性,
/// <summary> /// 表示當前Action請求為一個具體的功能頁面 /// </summary> public class AdminActionMethod : Attribute { /// <summary> /// 頁面請求路徑 /// </summary> public string ActionUrl { get; set; } /// <summary> /// 頁面操作代碼 /// </summary> public string RoleCode { get; set; } /// <summary> /// 頁面返回類型(0:返回頁面,1返回json格式) /// </summary> public int ActionResultType { get; set; } }
當不需要驗證的時候只要設置RoleCode="NoNeedAuthory"就行。
然后每次在執行方法之間都會進入到
public class AdminAuthory : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { //用MVC系統自帶的功能 獲取當前方法上的特性名稱 bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(NoNeedAdminAuthory), inherit: true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NoNeedAdminAuthory), inherit: true); if (skipAuthorization) { return; } //檢查是否登錄 if (!WebCookieHelper.AdminCheckLogin()) { filterContext.Result = new RedirectResult("~/Admin/Account/Login", true); return; } //如果是超級管理就免去驗證 if (WebCookieHelper.GetAdminId(5) == 1) { return; } //頁面權限驗證開始 var customAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true); if (customAttributes != null && customAttributes.Length > 0) { for (int i = 0; i < customAttributes.Count(); i++) { if (customAttributes.GetValue(i).GetType().Name == "AdminActionMethod") {//判斷anction特性名稱 string actionCode = (customAttributes[i] as AdminActionMethod).RoleCode;//獲取特性功能按鈕代碼 string actionUrl = (customAttributes[i] as AdminActionMethod).ActionUrl;//獲取特性功能地址 int actionResultType = (customAttributes[i] as AdminActionMethod).ActionResultType;//獲取返回視圖類型 if (actionCode == "NoNeedAuthory") {//不需要權限認證 return; } else { //判斷權限是否符合 List<AuthorDesign.Model.AdminPageAction> pageActionList = AdminMenuHelper.GetNowAdminMenu(); var pageSelect = pageActionList.Where(m => m.PageUrl == actionUrl); if (pageSelect != null && pageSelect.Count() > 0) { //判斷有無執行該頁面的權利 //判斷有誤執行該動作權利 var codeList = AdminMenuHelper.LoadActionCodeList(); //先根據動作按鈕代碼查找到代碼所在按鈕Id var codeSelect = codeList.Where(m => m.ActionCode == actionCode); if (codeSelect != null && codeSelect.Count() > 0) { int codeId = codeSelect.First().Id; JavaScriptSerializer serializer = new JavaScriptSerializer(); //判斷codeId在角色動作列表中是否為選擇狀態 string roleActionList = pageSelect.First().RoleActionList; List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> roleActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(roleActionList); if (roleActionListModel != null && roleActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == 1).Count() > 0) { //判斷CodeId在管理員動作列表中是否為選擇狀態 List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> adminActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(pageSelect.First().AdminActionList); if (adminActionListModel != null && adminActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == 1).Count() > 0) { StringBuilder sb = new StringBuilder(); sb.Append("["); //傳遞在該頁面可執行的按鈕 foreach (var item in roleActionListModel) { if (item.actionChecked == 1) { var needChangeAction = adminActionListModel.Where(m => m.ActionId == item.ActionId).FirstOrDefault(); if (needChangeAction == null) { item.actionChecked = 0; } else if (needChangeAction.actionChecked == 0) { item.actionChecked = 0; } } AuthorDesign.Model.PageAction OneAction = codeList.Where(m => m.Id == item.ActionId).FirstOrDefault(); sb.Append("{").Append("\"").Append("ActionName").Append("\"").Append(":").Append("\"").Append(OneAction == null ? "" : OneAction.ActionCode).Append("\"").Append(",").Append("\"").Append("IsChecked").Append("\"").Append(":").Append(item.actionChecked).Append("}").Append(","); } sb.Remove(sb.Length - 1, 1); sb.Append("]"); filterContext.Controller.ViewBag.CanOperationActionList = sb.ToString(); } else { if (actionResultType == 0) { filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true); } else if (actionResultType == 1) { filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暫無權限操作" } }; } return; } } else { if (actionResultType == 0) { filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true); } else if (actionResultType == 1) { filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暫無權限操作" } }; } return; } } else { if (actionResultType == 0) { filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true); } else if (actionResultType == 1) { filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暫無權限操作" } }; } return; } } else { if (actionResultType == 0) { filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true); } else if (actionResultType == 1) { filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暫無權限操作" } }; } return; } } } } } base.OnActionExecuting(filterContext); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class NoNeedAdminAuthory : Attribute { }
這是MVC的機制,這個方法是重寫了執行方法之前的這個方法,不過需要在控制器上或者方法上加上下面這個代碼
那么接下來就說下我的判斷思路:
//檢查是否登錄 if (!WebCookieHelper.AdminCheckLogin()) { filterContext.Result = new RedirectResult("~/Admin/Account/Login", true); return; }
這是用來先檢測下用戶是否登錄,如果沒有登錄則直接回到登錄頁面,
//如果是超級管理就免去驗證 if (WebCookieHelper.GetAdminId(5) == 1) { return; }
這是如果進來的用戶是超級管理員那么就直接顯示要顯示的頁面頁面即可,左邊菜單欄晚點講。
//頁面權限驗證開始 var customAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true); if (customAttributes != null && customAttributes.Length > 0) { for (int i = 0; i < customAttributes.Count(); i++) { if (customAttributes.GetValue(i).GetType().Name == "AdminActionMethod") {//判斷anction特性名稱 string actionCode = (customAttributes[i] as AdminActionMethod).RoleCode;//獲取特性功能按鈕代碼 string actionUrl = (customAttributes[i] as AdminActionMethod).ActionUrl;//獲取特性功能地址 int actionResultType = (customAttributes[i] as AdminActionMethod).ActionResultType;//獲取返回視圖類型
利用這個來抓取用戶當前要執行的方法,然后對其作出相應的處理,
List<AuthorDesign.Model.AdminPageAction> pageActionList = AdminMenuHelper.GetNowAdminMenu();
這行代碼用來加載當前要顯示的全部頁面
/// <summary> /// 獲取管理員可操作菜單列表 /// </summary> /// <param name="adminId">管理員Id</param> /// <returns></returns> public static List<Model.AdminPageAction> GetAdminMenu(int adminId) { if (CacheHelper.IsExistCache("AdminMenuList")) { Dictionary<int, List<Model.AdminPageAction>> adminMenuListDic = CacheHelper.GetCache("AdminMenuList") as Dictionary<int, List<Model.AdminPageAction>>; List<Model.AdminPageAction> adminMenuList = adminMenuListDic[adminId]; if (adminMenuList == null) { adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId); adminMenuListDic.Add(adminId, adminMenuList); CacheHelper.AddCache("AdminMenuList", adminMenuListDic, 2); } return adminMenuList; } else { List<Model.AdminPageAction> adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId); Dictionary<int, List<Model.AdminPageAction>> adminMenuListDic = new Dictionary<int, List<Model.AdminPageAction>>(); adminMenuListDic.Add(adminId, adminMenuList); CacheHelper.AddCache("AdminMenuList", adminMenuListDic, 2); return adminMenuList; } //if (CacheHelper.IsExistCache("AdminMenuList_"+adminId)) { // return CacheHelper.GetCache("AdminMenuList_" + adminId) as List<Model.AdminPageAction>; //} //else { // List<Model.AdminPageAction> adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId); // CacheHelper.AddCache("AdminMenuList_" + adminId, adminMenuList, 1); // return adminMenuList; //} //return EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId); } /// <summary> /// 獲取當前管理員可操作菜單列表(超級管理員另取) /// </summary> /// <returns></returns> public static List<Model.AdminPageAction> GetNowAdminMenu() { return GetAdminMenu(WebCookieHelper.GetAdminId(0)); }
這里我用緩存做了下處理,不知道處理的好不好,還望你們指點我一下。
var pageSelect = pageActionList.Where(m => m.PageUrl == actionUrl); if (pageSelect != null && pageSelect.Count() > 0) { //判斷有無執行該頁面的權利
這個是用來判斷當前執行的方法是否在全部要顯示的頁面之中,如果不是則直接輸出,是的話繼續往下走。
//判斷有誤執行該動作權利 var codeList = AdminMenuHelper.LoadActionCodeList(); //先根據動作按鈕代碼查找到代碼所在按鈕Id var codeSelect = codeList.Where(m => m.ActionCode == actionCode); if (codeSelect != null && codeSelect.Count() > 0) { int codeId = codeSelect.First().Id; JavaScriptSerializer serializer = new JavaScriptSerializer(); //判斷codeId在角色動作列表中是否為選擇狀態 string roleActionList = pageSelect.First().RoleActionList;
這里是先判斷了當前執行的方法按鈕是否在該管理員所屬的角色 可操作的按鈕之中,不是的話直接輸出,如果是的話則繼續往下走。
List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> roleActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(roleActionList); if (roleActionListModel != null && roleActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == 1).Count() > 0) { //判斷CodeId在管理員動作列表中是否為選擇狀態 List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> adminActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(pageSelect.First().AdminActionList); if (adminActionListModel != null && adminActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == 1).Count() > 0) { StringBuilder sb = new StringBuilder(); sb.Append("["); //傳遞在該頁面可執行的按鈕 foreach (var item in roleActionListModel) { if (item.actionChecked == 1) { var needChangeAction = adminActionListModel.Where(m => m.ActionId == item.ActionId).FirstOrDefault(); if (needChangeAction == null) { item.actionChecked = 0; } else if (needChangeAction.actionChecked == 0) { item.actionChecked = 0; } } AuthorDesign.Model.PageAction OneAction = codeList.Where(m => m.Id == item.ActionId).FirstOrDefault(); sb.Append("{").Append("\"").Append("ActionName").Append("\"").Append(":").Append("\"").Append(OneAction == null ? "" : OneAction.ActionCode).Append("\"").Append(",").Append("\"").Append("IsChecked").Append("\"").Append(":").Append(item.actionChecked).Append("}").Append(","); } sb.Remove(sb.Length - 1, 1); sb.Append("]"); filterContext.Controller.ViewBag.CanOperationActionList = sb.ToString();
這部分就是主要用來判斷當前執行的方法是否在該管理員可執行的按鈕之中,如果在的話那么將改頁面的按鈕以及是否可操作狀態通過ViewBag進行傳到前台,然后前台利用Js來移除相對應的不顯示按鈕。
左邊的菜單按鈕部分待會上源碼自己去看下吧
那么簡單的用戶角色權限管理在這里就可以結束了。但是我發現有個問題,我也不知道是為什么:看下面
就是我用火狐的時候,發現點擊某些鏈接的時候會不經過那個action的方法,直接跳到登錄頁面,這是為什么,我碰到好幾次了,求幫忙解決下。
github地址:https://github.com/yjqGitHub/AuthoryDesign
有什么地方寫的不好的還希望大家都指出來啊
