2019独角兽企业重金招聘Python工程师标准>>>
1.以前我们的权限主要靠手工录入到系统中,然后进行验证,这种方式不仅耗时,而且一旦按钮id 发生变动等情况 维护比较麻烦,现在我们采用直接从Controller中读取对应的action 进行设置权限,这样就不需要做过多维护以下是源码
///
/// 控制器操作类
///
public class ControllerHelper
{
private const string All_ControllerActionCacheKey = "All_System_ControllerHelper_Actions_List";
///
/// 获取所有页面的Action
///
public static List AuthAttributes
{
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 List GetAllActions()
{
#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 List 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权限基类,
主要用于定义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", "名称")]