1.之前咱們的權限主要靠手工錄入到系統中,而後進行驗證,這種方式不只耗時,並且一旦按鈕id 發生變更等狀況 維護比較麻煩,如今咱們採用直接從Controller中讀取對應的action 進行設置權限,這樣就不須要作過多維護如下是源碼html
/// <summary> /// 控制器操做類 /// </summary> public class ControllerHelper { private const string All_ControllerActionCacheKey = "All_System_ControllerHelper_Actions_List"; /// <summary> /// 獲取全部頁面的Action /// </summary> public static List<BasePermissionAttribute> AuthAttributes { get { return ApplicationEnvironments.CacheService.Get<List<BasePermissionAttribute>>(All_ControllerActionCacheKey, () => { return new ControllerHelper().GetAllActions(); }, true); } } /// <summary> /// 獲取單頁面的Action /// </summary> /// <param name="areaName"></param> /// <param name="controllerName"></param> /// <returns></returns> public static List<BasePermissionAttribute> GetActionsByPage(string areaName,string controllerName) { if (AuthAttributes != null && AuthAttributes.Count > 0) { return AuthAttributes.Where(x=>x.AreaName.ToLower().Equals(areaName.ToLower())&&x.ControllerName.ToLower().Equals(controllerName.ToLower())).ToList(); } return null; } /// <summary> /// 獲取全部頁面的Action /// </summary> private List<BasePermissionAttribute> GetAllActions() { #region 經過反射讀取Action方法寫入對應權限至集合 List<BasePermissionAttribute> authAttributes = new List<BasePermissionAttribute>(); //讀取當前項目程序集中集成自AdminController的控制器 var files = System.IO.Directory.GetFiles(AppContext.BaseDirectory, "*.Web.dll"); if (files != null && files.Length > 0) { foreach (var file in files) { var assembly = Assembly.LoadFrom(file); var types = assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(BaseController))).ToList(); //var now = DateTime.Now; foreach (var type in types) { //獲取全部action方法 GetControllerActions(type,ref authAttributes); } } } return authAttributes; #endregion } /// <summary> /// 獲取單個控制器中的Actions /// </summary> /// <param name="controller"></param> private void GetControllerActions(Type controller, ref List<BasePermissionAttribute> authAttributes) { var areaAttr= controller.GetCustomAttribute(typeof(AreaAttribute),true); string areaName = ""; if (areaAttr != null) { areaName = (areaAttr as AreaAttribute).RouteValue; } var members = controller.GetMethods().Where(e => e.ReturnType.Name == nameof(ActionResult) || e.ReturnType.Name == nameof(IActionResult) || e.ReturnType.Name == nameof(JsonResult) ); string[] systemAction = {"index","forgrid" }; foreach (var member in members) { if (systemAction.Contains(member.Name.ToLower())) { continue; } //獲取功能列表 var attr = member.GetCustomAttribute(typeof(BasePermissionAttribute), true) ; if (attr == null) continue; var auth = attr as BasePermissionAttribute; if (string.IsNullOrWhiteSpace(auth.ActionCode)|| !string.IsNullOrWhiteSpace(auth.ActionName) || auth.IsParent|| auth.NoAccess) { continue; } auth.AreaName = areaName; if (string.IsNullOrWhiteSpace(auth.ActionName)) { auth.ActionName = member.Name; } auth.ControllerName = controller.Name.Replace("Controller", ""); //功能對應的二級菜單 authAttributes.Add(auth); } } }
2.BasePermissionAttribute權限基類,ide
主要用於定義action 訪問屬性,因爲在底層須要引用該類方便存儲讀取controller中的action 因此須要這個基類,若是項目這個類放在業務層是不須要分開的post
public class BasePermissionAttribute :Attribute, IAsyncAuthorizationFilter { /// <summary> /// get請求是否須要驗證權限 默認是 /// </summary> public bool IsGet { get; set; } /// <summary> /// post請求是否須要驗證權限 默認是 /// </summary> public bool IsPost { get; set; } /// <summary> /// 描述 /// </summary> public string Description { get; set; } /// <summary> /// 與其它ActionName權限同樣 /// </summary> public string ActionCode { get; set; } /// <summary> /// Action名稱 /// </summary> public string ActionName { get; set; } /// <summary> /// 域名稱 /// </summary> public string AreaName { get; set; } /// <summary> /// 控制器名稱 /// </summary> public string ControllerName { get; set; } /// <summary> /// 是否繼承controller Index訪問權限 /// </summary> public bool IsParent { get; set; } /// <summary> /// 不容許訪問 /// </summary> public bool NoAccess { get; set; } //public PermissionAttribute() //{ // IsGet = true; // IsPost = true; //} public BasePermissionAttribute() { IsGet = true; IsPost = true; IsParent = false; } public BasePermissionAttribute(string code,string description) { IsGet = true; IsPost = true; IsParent = false; ActionCode = "BTN" + code; Description = description; } /// <summary> /// 輸出錯誤信息 /// </summary> /// <param name="filterContext"></param> /// <param name="strError"></param> public void WriteResult(AuthorizationFilterContext filterContext, string strError) { var areaName = ""; var actionName = filterContext.RouteData.Values["Action"].ToString(); var controllerName = filterContext.RouteData.Values["controller"].ToString(); if (filterContext.RouteData.DataTokens["area"] != null) { areaName = filterContext.RouteData.DataTokens["area"].ToString(); } //new LogErrorService().Save((!string.IsNullOrEmpty(areaName)?areaName+"/"+controllerName:controllerName),actionName,strError,strError); if (AppHttpContext.IsPost&&AppHttpContext.IsAjax) { filterContext.HttpContext.Response.StatusCode = 200; filterContext.Result = new JsonResult(AjaxResult.Error(strError, -100)); } else { var view = new ViewResult(); view.ViewName = "~/Views/Home/Error.cshtml"; view.ViewData = new Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary(new BaseController().ViewData); view.ViewData["Message"] = strError; view.ViewData["Exception"] = new Exception(strError); filterContext.Result = view; } } public virtual Task OnAuthorizationAsync(AuthorizationFilterContext filterContext) { return Task.CompletedTask; }
3.權限的具體實現this
public class PermissionAttribute : BasePermissionAttribute { public PermissionAttribute():base() { } /// <summary> /// /// </summary> /// <param name="code">權限標識(controller中請勿重複)</param> /// <param name="description">描述</param> public PermissionAttribute(string actionCode, string description) : base(actionCode, description) { } public override Task OnAuthorizationAsync(AuthorizationFilterContext filterContext) { //匿名標識 無需驗證 if (filterContext.Filters.Any(e => (e as AllowAnonymousAttribute) != null)) return Task.CompletedTask; if ((AppHttpContext.IsPost && !IsPost)||(!AppHttpContext.IsPost && !IsGet)) { return Task.CompletedTask; } if (NoAccess) { WriteResult(filterContext, "該接口不容許訪問"); return Task.CompletedTask; } if (!AppHttpContext.Current.User.Identity.IsAuthenticated) { WriteResult(filterContext, "未登陸,無權訪問"); return Task.CompletedTask; } var userEntity = ApplicationEnvironments.DefaultSession.GetUser<UserEntity>(); if (userEntity == null) { WriteResult(filterContext, "對不起,您無權訪問"); return Task.CompletedTask; } //獲取請求的區域,控制器,action名稱 this.AreaName = string.IsNullOrWhiteSpace(this.AreaName) ? filterContext.RouteData.Values["area"]?.ToString() : this.AreaName; this.ControllerName = string.IsNullOrWhiteSpace(this.ControllerName) ? filterContext.RouteData.Values["controller"]?.ToString() : this.ControllerName; this.ActionName = string.IsNullOrWhiteSpace(this.ActionName) ? filterContext.RouteData.Values["action"]?.ToString() : this.ActionName; if (IsParent) { this.ActionName = "Index"; } var isPermit = false; if (string.IsNullOrWhiteSpace(ControllerName) || ControllerName.ToLower().Equals("home")) { ControllerName = ""; } if (string.IsNullOrWhiteSpace(ActionName) || ActionName.ToLower().Equals("index")) { ActionName = ""; } string routeUrl = ""; routeUrl = (!string.IsNullOrWhiteSpace(AreaName) ? AreaName + "/" : "").ToLower(); if(!string.IsNullOrWhiteSpace(ControllerName)) { routeUrl += ControllerName.ToLower() + (!string.IsNullOrWhiteSpace(ActionName) ? "/" : ""); } routeUrl += ActionName.ToLower(); var isUmPermit = userEntity.UnPermission.Where(x => x.RouteUrl.ToLower().Equals(routeUrl)).FirstOrDefault() != null; if (!isUmPermit) { isPermit = userEntity.Permission.Where(x => x.RouteUrl.ToLower().Equals(routeUrl)).FirstOrDefault() != null; if (isPermit) { return Task.CompletedTask; } } WriteResult(filterContext, "對不起,您無權訪問"); return Task.CompletedTask; } }
4.在action 上增長以下代碼 便可code
[Permission("Code", "名稱")]