1.以前我们的权限主要靠手工录入到系统中,然后进行验证,这种方式不仅耗时,而且一旦按钮id 发生变动等情况 维护比较麻烦,现在我们采用直接从Controller中读取对应的action 进行设置权限,这样就不需要做过多维护以下是源码
////// 控制器操作类 /// public class ControllerHelper { private const string All_ControllerActionCacheKey = "All_System_ControllerHelper_Actions_List"; ////// 获取所有页面的Action /// public static ListAuthAttributes { get { return ApplicationEnvironments.CacheService.Get
>(All_ControllerActionCacheKey, () => { return new ControllerHelper().GetAllActions(); }, true); } } /// /// 获取单页面的Action /// /// /// ///public static List 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; } /// /// 获取所有页面的Action /// private ListGetAllActions() { #region 通过反射读取Action方法写入对应权限至集合 List authAttributes = new List (); //读取当前项目程序集中集成自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 } /// /// 获取单个控制器中的Actions /// /// private void GetControllerActions(Type controller, ref ListauthAttributes) { 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权限基类,
主要用于定义action 访问属性,由于在底层需要引用该类方便存储读取controller中的action 所以需要这个基类,如果项目这个类放在业务层是不需要分开的
public class BasePermissionAttribute :Attribute, IAsyncAuthorizationFilter { ////// get请求是否需要验证权限 默认是 /// public bool IsGet { get; set; } ////// post请求是否需要验证权限 默认是 /// public bool IsPost { get; set; } ////// 描述 /// public string Description { get; set; } ////// 与其它ActionName权限一样 /// public string ActionCode { get; set; } ////// Action名称 /// public string ActionName { get; set; } ////// 域名称 /// public string AreaName { get; set; } ////// 控制器名称 /// public string ControllerName { get; set; } ////// 是否继承controller Index访问权限 /// public bool IsParent { get; set; } ////// 不允许访问 /// 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; } ////// 输出错误信息 /// /// /// 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.权限的具体实现
public class PermissionAttribute : BasePermissionAttribute { public PermissionAttribute():base() { } ////// /// /// 权限标识(controller中请勿重复) /// 描述 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(); 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 上增加如下代码 即可
[Permission("Code", "名称")]