.NET Core 反射获取所有控制器及方法上特定标签

有个需求,就是在. NET Core中,我们想在项目 启动时,获取LinCmsAuthorizeAttribute这个特性标签所有出现的地方,把他的参数,放入一个集合并缓存起来,以便后面使用此数据用于权限验证。

我们通过反射获取所有控制器下及方法的Attribute。

LinCmsAuthorizeAttribute是什么

其代码非常简单,用于自定义权限验证,通过重写OnAuthorizationAsync方法,实现固定权限可分配给动态角色(也能分配给动态用户)。主要就基于权限的授权的实现进行研究,实现方法级别的权限验证。

当然,这个只是部分代码,完整代码请查看最下方开源地址,其中LinCmsAuthorizeAttribute继承AuthorizeAttribute,拥有指定角色权限控制,当Permission未指定时,当过滤器与Authorize功能相同。Module是指模块,即多个权限,属于同一个模块,方便前台展示为树型结构。Permission属性的值不可重复。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class LinCmsAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public string Permission { get; set; }
public string Module { get; set; } public LinCmsAuthorizeAttribute()
{ } public LinCmsAuthorizeAttribute(string permission,string module)
{
Permission = permission;
Module = module;
} public LinCmsAuthorizeAttribute(string permission,string module, string policy) : base(policy)
{
Permission = permission;
Module = module;
} public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (Permission == null) return;
var authorizationService = (IAuthorizationService)context.HttpContext.RequestServices.GetService(typeof(IAuthorizationService));
var authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null, new OperationAuthorizationRequirement() { Name = Permission });
if (!authorizationResult.Succeeded)
{
context.Result = new ForbidResult();
}
} public override string ToString()
{
return $"\"{base.ToString()}\",\"Permission:{Permission}\",\"Module:{Module}\",\"Roles:{Roles}\",\"Policy:{Policy}\",\"AuthenticationSchemes:{AuthenticationSchemes}\"";
}
}

Controller

在 LinCms.Web中的Controller,至于为什么Permission为中文,目前的主要原因,此项目用于适配 Lin-CMS-VUE项目,所以于平常我们以某个字符串作为权限名不同,但不须大精小怪,道理相同。

[Route("cms/log")]
[ApiController]
public class LogController : ControllerBase
{
private readonly ILogService _logService; public LogController(ILogService logService)
{
_logService = logService;
} [HttpGet("users")]
[LinCmsAuthorize("查询日志记录的用户", "日志")]
public List<string> GetLoggedUsers([FromQuery]PageDto pageDto)
{
return _logService.GetLoggedUsers(pageDto);
} [HttpGet]
[LinCmsAuthorize("查询所有日志", "日志")]
public PagedResultDto<LinLog> GetLogs([FromQuery]LogSearchDto searchDto)
{
return _logService.GetLogUsers(searchDto);
} [HttpGet("search")]
[LinCmsAuthorize("搜索日志", "日志")]
public PagedResultDto<LinLog> SearchLogs([FromQuery]LogSearchDto searchDto)
{
return _logService.GetLogUsers(searchDto);
}
}

测试类获取方法上的特定标签

in xunit test 项目工程中,开始我们的测试

[Fact]
public void GetAssemblyMethodsAttributes()
{
var assembly = typeof(Startup).Assembly.GetTypes().AsEnumerable()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToList(); assembly.ForEach(r =>
{
foreach (var methodInfo in r.GetMethods())
{
foreach (Attribute attribute in methodInfo.GetCustomAttributes())
{
if (attribute is LinCmsAuthorizeAttribute linCmsAuthorize)
{
_testOutputHelper.WriteLine(linCmsAuthorize.ToString());
}
}
}
});
}

方法结果

可在输出文本中查看,正是我们想要的东西,最后一行,是其他Controller中的内容,而且我们重写了ToString(),所以我们能看到其属性。

"LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:查询日志记录的用户","Module:日志","Roles:","Policy:","AuthenticationSchemes:"
"LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:查询所有日志","Module:日志","Roles:","Policy:","AuthenticationSchemes:"
"LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:搜索日志","Module:日志","Roles:","Policy:","AuthenticationSchemes:"
"LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:查看lin的信息","Module:信息","Roles:","Policy:","AuthenticationSchemes:"

获取控制器上特性标签

/// <summary>
/// 获取控制器上的LinCmsAuthorizeAttribute
/// </summary>
/// "LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:","Module:","Roles:Administrator","Policy:","AuthenticationSchemes:"
[Fact]
public void GetControllerAttributes()
{
var assembly = typeof(Startup).Assembly.GetTypes().AsEnumerable()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToList(); assembly.ForEach(d =>
{
var linCmsAuthorize = d.GetCustomAttribute<LinCmsAuthorizeAttribute>();
if (linCmsAuthorize != null)
{
_testOutputHelper.WriteLine(linCmsAuthorize.ToString());
}
});
}

Controller结果

只有AdminController加了此标签,所以只有一行。

"LinCms.Zero.Authorization.LinCmsAuthorizeAttribute","Permission:","Module:","Roles:Administrator","Policy:","AuthenticationSchemes:"

此时Roles为Administrator,Permission及Module都是null,

这是因为只有AdminController中加了LinGroup.Administrator="Administrator"字符串,在登录过程中,已经给当前登录用户设置了 new Claim(ClaimTypes.Role,user.IsAdmin()?LinGroup.Administrator:user.GroupId.ToString()),即"Administrator,当用户访问AdminController中的方法时,LinCmsAuthorize并没有做相关验证,都是AuthorizeAttribute,实现了固定角色权限的判断及登录的判断。LinCmsAuthorize完成了固定权限设置为不同的动态角色后,判断用户是否拥有此权限。

[LinCmsAuthorize(Roles = LinGroup.Administrator)]
public class AdminController : ControllerBase
{
...
}

参考

开源地址

.NET Core 反射获取所有控制器及方法上特定标签的更多相关文章

  1. java通过反射获取调用变量以及方法

    一:反射概念 可以通过Class类获取某个类的成员变量以及方法,并且调用之. 二:通过反射获取方法.变量.构造方法 @Test // 通过反射获取类定义的方法 public void testMeth ...

  2. 2019-4-16-C#-使用反射获取私有属性的方法

    title author date CreateTime categories C# 使用反射获取私有属性的方法 lindexi 2019-4-16 10:13:3 +0800 2018-09-26 ...

  3. C#通过反射获取类中的方法和参数个数,反射调用方法带参数

    using System; using System.Reflection; namespace ConsoleApp2 { class Program { static void Main(stri ...

  4. C# 使用反射获取私有属性的方法

    本文告诉大家多个不同的方法使用反射获得私有属性,最后通过测试性能发现所有的方法的性能都差不多 在开始之前先添加一个测试的类 public class Foo { private string F { ...

  5. 第五课 JAVA反射获取对象属性和方法(通过配置文件)

    Service1.java package reflection; public class Service1 { public void doService1(){ System.out.print ...

  6. 第五课 JAVA反射获取对象属性和方法

    package com.hero; import java.lang.reflect.Field; public class TestReflction5 { public static void m ...

  7. .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)——转载

    原文链接:https://blog.walterlv.com/post/dotnet-high-performance-reflection-suggestions.html ***** 大家都说反射 ...

  8. 原 .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)

    大家都说反射耗性能,但是到底有多耗性能,哪些反射方法更耗性能:这些问题却没有统一的描述. 本文将用数据说明反射各个方法和替代方法的性能差异,并提供一些反射代码的编写建议.为了解决反射的性能问题,你可以 ...

  9. Java反射学习-3 - 反射获取属性,方法,构造器

    package cn.tx.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import ...

随机推荐

  1. 通用权限管理系统组件 (GPM - General Permissions Manager)

    有的公司开发人员只那么几个,一个人支撑整个公司所有的IT系统实在有点累,不想自己写权限系统了,自己琢磨不也是要花时间和精力,要为此付出多少时间和汗水阿,细细的皱纹不知要多多少呢,重复建设不是白白浪费生 ...

  2. Clickhosue 强大的函数,argMin() 和argMax()函数

    说实话,我喜欢Clickhouse 的函数,简单操作,功能强大.今天需要给大家介绍两个函数,argMin(),argMax() 1.argMax():计算 ‘arg’ 最大值 ‘val’ 价值. 如果 ...

  3. OpenRASP管理后台安装记录

    OpenRASP项目地址https://rasp.baidu.com/ 一.安装java 在CentOS中安装ElasticSearch需要Java1.8.0,可执行命令java -version查看 ...

  4. 杭电的题,输出格式卡的很严。HDU 1716 排列2

    题很简单,一开始写代码,是用整数的格式写的,怎么跑都不对,就以为算法错了,去看大佬们的算法STL全排列:next_permutation(); 又双叒叕写了好几遍,PE了将近次,直到跑了大佬代码发现, ...

  5. 【漏洞预警】SaltStack远程命令执行漏洞 /tmp/salt-minions

    前言:   2020年5月3日,阿里云应急响应中心监测到近日国外某安全团队披露了SaltStack存在认证绕过致命令执行漏洞以及目录遍历漏洞.在多个微信群和QQ群已经有群友反映中招,请马上修复. 以下 ...

  6. Flutter 粘合剂CustomScrollView控件

    老孟导读:快乐的51假期结束了,切换为努力模式,今天给大家分享CustomScrollView组件,此组件在以后的项目中会经常用到,CustomScrollView就像一个粘合剂,将多个组件粘合在一起 ...

  7. CTF-Pwn-[BJDCTF 2nd]diff

    CTF-Pwn-[BJDCTF 2nd]diff 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!本文仅用于学习与交流,不得用于非 ...

  8. E - Help Jimmy POJ - 1661 dp

    E - Help Jimmy POJ - 1661 这个题目本身不是很难,但是可以更加优化这个写法. 开始是n*n #include <cstdio> #include <cstri ...

  9. 在web项目中使用shiro(记住我功能)

    第一步,添加“记住我”复选框,rememberMe要设置参数 第二步,配置shiro的主配置文件 注意 rememberMeCookie对应的bean中要声明 <constructor-arg ...

  10. 201771010113 李婷华 《面向对象程序设计(Java)》第六周总结

    一.理论知识部分 第四章 类与对象 1.方法的定义:方法声明和方法体. 2.重载:一个类中可以有多个方法具有相同的名字,不同的类型,不同的参数. 3.构造器:也叫构造方法,是类中的一种特殊的方法,其作 ...