asp.net core权限模块的快速构建

大部分系统都会有权限模块,别人家系统的权限怎么生成的我不知道,我只知道这样做是可以并且挺好的。
文章中只对asp.net core的部分代码进行说明 呃 记录~,mvc版本自行前往仓库查阅
代码中的一些特性标记后面列出,或前往仓库查看~

1.根据特性标记生成模块权限

先上效果图,感兴趣的前往Demo仓库地址,不感兴趣的关闭页面吧~

图片

模型定义

Demo中菜单分为三级,首先使用枚举定义模块,FirstModuleMenu为一级菜单,SecondModuleMenu为二级菜单,三级菜单在action方法上由PermissionDescription标识并IsMenu=true的方法
若是页面功能则为IsMenu=false
可使用的特性标记还包含以下几种,并且权限验证时依次递增:

  • 免登录:AllowAnonymous
  • 管理员默认权限: NonePermissionAttribute
  • 指定权限: PermissionDescriptionAttribute
  • 依赖权限(包含有这些的任一权限都将获得授权): ParentPermissionAttribute
    //一级菜单public class FirstModuleMenu{public const string 系统管理 = "系统|icon-setting";public const string 用户管理 = "用户|icon-user";}//二级菜单public enum SecondModuleMenu{[Description(FirstModuleMenu.系统管理)]系统设置,[Description(FirstModuleMenu.用户管理)]用户管理,}//三级菜单[PermissionDescription(SecondModuleMenu.系统设置, "站点设置", true)]public ActionResult SiteSetting(){return Content("站点设置 System/SiteSetting");}

生成权限模型集合

定义权限模型 SysModule.cs
调用初始化权限方法

    private static List<SysModule> _AllAdminModule { get; set; } = new List<SysModule>();/// <summary>/// 初始化权限/// </summary>public static void InitPermission(){var result = new List<SysModule>();#region 通过反射读取Action方法写入对应权限至集合//读取CoreDemo程序集中集成自AdminController的控制器var types = Assembly.Load("CoreDemo").GetTypes().Where(e => e.BaseType.Name == nameof(AdminController));var area = "";//默认未使用区域var now = DateTime.Now;var i = 1;foreach (var type in types){//获取所有action方法var members = type.GetMethods().Where(e => e.ReturnType.Name == nameof(ActionResult) || e.ReturnType.Name == nameof(IActionResult));foreach (var member in members){//获取功能列表var attrs = member.GetCustomAttributes(typeof(PermissionDescriptionAttribute), true);if (attrs.Length == 0)continue;//功能对应的二级菜单var parentMenuEnum = (attrs[0] as PermissionDescriptionAttribute).ParentMenu;var parentMenuName = parentMenuEnum.ToString();//功能对应的一级菜单 名称|icon类名var enumArry = parentMenuEnum.GetEnumDescription().Split('|');var mainMenuName = enumArry[0];var existMainMenu = result.Where(e => e.ModuleName == mainMenuName).FirstOrDefault();if (existMainMenu == null){var mainMenu = new SysModule(){Id = i,ParentId = 0,ModuleName = mainMenuName,Icon = enumArry[1] ?? "",Area = area,Controller=string.Empty,Action=string.Empty,IsMenu = true,IsVisible = true,Remark = string.Empty,DisplayOrder = i,CreateTime = now};i++;existMainMenu = mainMenu;existMainMenu.Children = new List<SysModule>();//添加一级菜单result.Add(existMainMenu);}var existParentMenu = existMainMenu.Children.Where(e => e.ModuleName == parentMenuName).FirstOrDefault();if (existParentMenu == null){var parentMenu = new SysModule(){Id = i,ParentId = existMainMenu.Id,ModuleName = parentMenuName,Icon=string.Empty,Area = area,Controller = string.Empty,Action = string.Empty,IsMenu = enumArry.Length != 3 || bool.Parse(enumArry[2]),IsVisible = true,DisplayOrder = i,CreateTime = now,Children = new List<SysModule>()};i++;existParentMenu = parentMenu;existParentMenu.Children = new List<SysModule>();existMainMenu.Children.Add(existParentMenu);//添加二级菜单result.Add(existParentMenu);}var menu = new SysModule(){Id = i,ParentId = existParentMenu.Id,Area = area,Action = member.Name,DisplayOrder = i,CreateTime = now,Controller = member.DeclaringType.Name.Substring(0, member.DeclaringType.Name.Length - 10),IsMenu = (attrs[0] as PermissionDescriptionAttribute).IsMenu,Children = new List<SysModule>(),};if (menu.IsMenu)menu.IsVisible = true;menu.ModuleName = (attrs[0] as PermissionDescriptionAttribute).FuncName;i++;existParentMenu.Children.Add(menu);result.Add(menu);}}#endregion//todo 添加到数据库_AllAdminModule = result;}

2.使用过滤器拦截请求进行验证

新建特性标记 AdminAuthorizeAttribute 继承Attribute类以及实现IAuthorizationFilter接口的OnAuthorization方法
不多说,上图

图片

不多说,上代码↓_↓

权限验证过滤器:AdminAuthorizeAttribute

    //后台权限验证public class AdminAuthorizeAttribute : Attribute,IAuthorizationFilter{public void OnAuthorization(AuthorizationFilterContext filterContext){//匿名标识 无需验证if (filterContext.Filters.Any(e => (e as AllowAnonymous) != null))return;var adminInfo = GlobalContext.AdminInfo;//此处应为获取的登录用户if (adminInfo == null){if(filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest"){filterContext.Result = new JsonResult("未登录");}else{filterContext.Result =new ContentResult() { Content = "未登录" };}return;}//对应action方法或者Controller上若存在NonePermissionAttribute标识,即表示为管理员的默认权限,只要登录就有权限var isNone = filterContext.Filters.Any(e => (e as NonePermissionAttribute) != null);if (isNone)return;//获取请求的区域,控制器,action名称var area = filterContext.RouteData.DataTokens["area"]?.ToString();var controller = filterContext.RouteData.Values["controller"]?.ToString();var action = filterContext.RouteData.Values["action"]?.ToString();var isPermit = false;//校验权限isPermit = ServiceFactory.CheckAdminPermit(adminInfo.Id, area, controller, action);if (isPermit)return;//此action方法的父辈权限判断,只要有此action对应的父辈权限,皆有权限访问var pAttrs = filterContext.Filters.Where(e => (e as ParentPermissionAttribute) != null).ToList();if (pAttrs.Count > 0){foreach (ParentPermissionAttribute pattr in pAttrs){if (!string.IsNullOrEmpty(pattr.Area))area = pattr.Area;isPermit = ServiceFactory.CheckAdminPermit(adminInfo.Id, area, pattr.Controller, pattr.Action);if (isPermit)return;}}if (!isPermit){filterContext.Result = new ContentResult() { Content = "无权限访问" };return;}}}

自定义特性标记,用于权限校验

此处的自定义的特性标记不能继承Attribute,因无法在AdminAuthorizeAttribute中的上下文filterContext.Filters中获取到特性标记(不知道咋取特性标记,所以用这种方式代替,也更为简单 冏)
!!!!!!!!!修改: 之前脑袋没有转过弯来,要使过滤器上下文的Filters中发现自定义过滤器需要继承 Attribute, IFilterMetadata

    /// <summary>/// 管理员的默认权限/// </summary>public class NonePermissionAttribute : Attribute, IFilterMetadata{}/// <summary>/// 匿名验证/// </summary>public class AllowAnonymous : Attribute, IFilterMetadata{}/// <summary>/// 长辈权限/// </summary>[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]public class ParentPermissionAttribute : Attribute, IFilterMetadata{/// <summary>/// 区域/// </summary>public string Area { get; set; }/// <summary>/// 控制器/// </summary>public string Controller { get; set; }/// <summary>/// Action名称/// </summary>public string Action { get; set; }public ParentPermissionAttribute(string area, string controller, string action){this.Area = area;this.Controller = controller;this.Action = action;}public ParentPermissionAttribute(string controller, string action){this.Controller = controller;this.Action = action;}}

若将代码全部贴出,有点略显多余,故,只贴出了部分核心代码.其他一些模型,扩展 请直奔仓库地址...
或使用git命令克隆MvcPermission分支到MvcPermission文件夹:git clone https://git.coding.net/yimocoding/WeDemo.git -b MvcPermission

补充

  • 2017-09-29
    突然灵光一现,将文中的ResultFilterAttribute特性标记替换为Attribute, IFilterMetadata ,果然可以~
    故得出:实现了IFilterMetadata的特性标记能够在过滤器的上下文中获取到。

转载于:https://www.cnblogs.com/morang/p/7606843.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/487500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度长文:AMD的崛起、衰落与复兴

来源&#xff1a;内容编译自「techspot」&#xff0c;谢谢。AMD是最早的大型微处理器设计者之一&#xff0c;近50年来一直是技术爱好者之间争论的话题。它的历史构成了一个激动人心的故事——充满了英雄式的成功&#xff0c;愚蠢的错误。在其他半导体公司来来往往的时候&#x…

数据结构-使用两个栈实现一个队列

1&#xff1a;如何只使用stack实现queue呢&#xff1f;我们知道stack是先进后出的&#xff08;FIFO&#xff09;&#xff0c;而queue是先进先出的&#xff08;FIFO&#xff09;。也就是说&#xff0c;stack进行了一次反向。如果进行两次反向&#xff0c;就能实现queue的功能&am…

5G时代下,边缘计算产品的未来展望

来源&#xff1a;北京物联网智能技术应用协会首发于人人都是产品经理。一、边缘计算市场潜力1. 5G基建如火如荼&#xff0c;万物互联互融将成为新战场2019年6月6号上午工信部宣布正式为中国移动、中国联通、中国电信、中国广电四家企业颁发5G牌照&#xff0c;中国正式进入5G元年…

使用Xcode进行iOS设备无线调试

设备环境&#xff1a;Mac OSX 10.12.5、iOS11、Xcode9PS:这是WWDC2017的新功能&#xff0c;iOS11以上&#xff0c;Xcode9这是刚性要求。这个功能不好找&#xff0c;就记下来了 手机连接上Xcode&#xff0c;打开Xcode菜单&#xff1a;Windows->Device and Simulators。找到连…

java 请求url 返回数据_java后台发起get请求获取响应数据|chu

本文实例为大家分享了java后台发起get请求获取响应数据&#xff0c;供大家参考&#xff0c;具体内容如下学习记录&#xff1a;话不多说直接上代码&#xff1a;package com.jl.chromeTest; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.H…

Android Studio 设置字体

File->Settings->Editor->Colors & Fonts->Font->Editor Font 转载于:https://www.cnblogs.com/WJQ2017/p/7608370.html

这三个博弈论新趋势,正深刻影响深度强化学习

来源 | AI科技评论作者 | Jesus Rodriguez编译 | 亚尔曼•佩皮校对 | 丛末 & Camel博弈论在现代人工智能&#xff08;AI&#xff09;解决方案中正扮演着至关重要的角色&#xff0c;深度强化学习&#xff08;DRL&#xff09;正是积极拥抱博弈论的头等公民。从单智能体程序到…

Beam概念学习系列之Pipeline 数据处理流水线

不多说&#xff0c;直接上干货&#xff01; Pipeline 数据处理流水线 Pipeline将Source PCollection ParDo、Sink组织在一起形成了一个完整的数据处理的过程。 Beam概念学习系列之PCollection数据集 Beam概念学习系列之PTransform数据处理转载于:https://www.cnblogs.com/zlslc…

美国再出半导体新法案!1800亿谋求芯片制造振兴

文章来源&#xff1a;EE Times、James E.Risch芯东西&#xff08;ID&#xff1a;aichip001&#xff09;编 | 董温淑芯东西7月1日消息&#xff0c;上周&#xff0c;多位美国两党议员共同提出《2020美国晶圆代工法案&#xff08;AFA&#xff0c;The American Foundries Act Of 20…

stackexchange.mysql_.net core使用redis基于StackExchange.Redis

.net core使用redis基于StackExchange.Redis教程&#xff0c;具体如下一.添加引用包StackExchange.RedisMicrosoft.Extensions.Configuration二.修改配置文件 appsettings.json{"RedisConfig": {"Redis_Default": {"Connection": "127.0.0.…

Apache网站服务

Apache 下载地址&#xff1a; http://mirror.bit.edu.cn/apache/httpd/相关软件下载地址&#xff1a;http://mirror.bjtu.edu.cn/apache/apr/apr          http://mirror.bjtu.edu.cn/apache/apr/apr-utilApache 简介&#xff1a; 进程技术&#xff0c;高资源消耗&…

微积分的发展史

来源&#xff1a;数学中国早期萌芽时期&#xff1a;1、 古西方萌芽时期&#xff1a;公元前七世纪&#xff0c;泰勒斯对图形的面积、体积与的长度的研究就含有早期微积分的思想&#xff0c;尽管不是很明显。公元前三世纪&#xff0c;伟大的全能科学家阿基米德利用穷竭法推算出了…

c# mysql代码中写事务_代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性...

[c#]代码库代码中使用事务前提&#xff1a;务必保证一个功能(或用例)在同一个打开的数据连接上&#xff0c;放到同一个事务里面操作。首先是在D层添加一个类为了保存当前操作的这一个连接放到一个事务中执行&#xff0c;并事务执行打开同一个连接、事务完成关闭同一个连接的一个…

AI的“色差”与“纠偏”

来源&#xff1a;脑极体在美国学术界声援BLM&#xff08;Black Lives Matter&#xff09;之后&#xff0c;事情的走向有点难以预料。学术界的反种族歧视反省似乎没有了下文&#xff0c;但是如火如荼的BLM运动早已蔓延开来&#xff0c;这次将矛头指向了AI界。事情的起因是杜克大…

英伟达奔驰共同发布自动驾驶系统,还自带停车功能

大数据文摘出品来源&#xff1a;VB编译&#xff1a;白浩然最近&#xff0c;英伟达&#xff08;Nvidia&#xff09;宣布为了和奔驰&#xff08;Mercedes-Benz&#xff09;汽车紧密合作&#xff0c;计划从2024年开始推出一款车载计算系统和AI基础设施&#xff0c;该技术于去年1月…

【hihocoder 1312】搜索三·启发式搜索(启发式搜索写法)

【题目链接】:http://hihocoder.com/problemset/problem/1312?sid1092363 【题意】 【题解】 定义一个A*函数 f stepval 这里的val是当前这个状态;每个点到目标状态的点的曼哈顿距离的绝对值; (这个值肯定比真正需要花费的路程短) step就为当前状态花费的步数; 把普通…

Gartner发布2020年数据与分析领域的十大技术趋势

来源&#xff1a;Gartner公司近日&#xff0c;Gartner发布了数据与分析领域的十大技术趋势&#xff0c;为数据和分析领导者的新冠疫情&#xff08;COVID-19&#xff09;响应和恢复工作提供指导&#xff0c;并为疫情后的重启做好准备。数据和分析领导者如果希望在疫情后能持续创…

java 中文域名转码_转换java方法

java date String 类型相互转换这种转换要用到java.text.SimpleDateFormat类字符串转换成日期类型&#xff1a;方法1&#xff1a;也是最简单的方法 Date datenew Date("2008-04-14");方法2&#xff1a;SimpleDateFormat sdfnew SimpleDateFormat("yyyy-M...文章…

【42.59%】【codeforces 602A】Two Bases

time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard output After seeing the “ALL YOUR BASE ARE BELONG TO US” meme for the first time, numbers X and Y realised that they have different bases, which complic…

java2019 数据结构算法面试题_2019年JVM最新面试题,必须收藏它

1、JVN内存结构方法区和对是所有线程共享的内存区域&#xff1b;而java栈、本地方法栈和程序员计数器是运行是线程私有的内存区域。Java堆(Heap),是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域&#xff0c;在虚拟机启动时创建。此内存区域的唯一…