.NET Core 反射获取所有控制器及方法上特定标签
.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
{
...
}
参考
- c# – 如何在asp. net core rc2中获取控制器的自定义属性 https://codeday.me/bug/20181207/453278.html
开源地址
.NET Core 反射获取所有控制器及方法上特定标签的更多相关文章
- java通过反射获取调用变量以及方法
一:反射概念 可以通过Class类获取某个类的成员变量以及方法,并且调用之. 二:通过反射获取方法.变量.构造方法 @Test // 通过反射获取类定义的方法 public void testMeth ...
- 2019-4-16-C#-使用反射获取私有属性的方法
title author date CreateTime categories C# 使用反射获取私有属性的方法 lindexi 2019-4-16 10:13:3 +0800 2018-09-26 ...
- C#通过反射获取类中的方法和参数个数,反射调用方法带参数
using System; using System.Reflection; namespace ConsoleApp2 { class Program { static void Main(stri ...
- C# 使用反射获取私有属性的方法
本文告诉大家多个不同的方法使用反射获得私有属性,最后通过测试性能发现所有的方法的性能都差不多 在开始之前先添加一个测试的类 public class Foo { private string F { ...
- 第五课 JAVA反射获取对象属性和方法(通过配置文件)
Service1.java package reflection; public class Service1 { public void doService1(){ System.out.print ...
- 第五课 JAVA反射获取对象属性和方法
package com.hero; import java.lang.reflect.Field; public class TestReflction5 { public static void m ...
- .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)——转载
原文链接:https://blog.walterlv.com/post/dotnet-high-performance-reflection-suggestions.html ***** 大家都说反射 ...
- 原 .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
大家都说反射耗性能,但是到底有多耗性能,哪些反射方法更耗性能:这些问题却没有统一的描述. 本文将用数据说明反射各个方法和替代方法的性能差异,并提供一些反射代码的编写建议.为了解决反射的性能问题,你可以 ...
- Java反射学习-3 - 反射获取属性,方法,构造器
package cn.tx.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import ...
随机推荐
- apache调优技巧之一隐藏apahce版本信息
如果你的服务器版本信息是这样的,是很 危险的. [root@xinsz63 httpd-2.2.27]# curl -I 192.168.1.38 HTTP/1.1 403 Forbidden Dat ...
- VUE简单整理
在用 Vue.js 构建大型应用时推荐使用 NPM 安装: # 最新稳定版 $ cnpm install vue 命令行工具 Vue.js 提供一个官方命令行工具,可用于快速搭建大型单页应用. # 全 ...
- OSG程序设计之Hello World 3.0
直接上代码: #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgViewer/View ...
- 从垃圾回收机制解析为什么局部内部类只能访问final修饰的局部变量以及为什么加final能解决问题
我们先稍微看一下代码: 从这里的提示可以看到,必须要将a的修饰符变为final才行. 现在笔者就这一结果做出自己的分析: 首先来说,我们知道,方法被调用时会执行,当执行的时候,方法中的局部变量会加载到 ...
- Code::Blocks无法调试 Starting the debuggee failed: No executable specified, use `target exec'
1.必须建立工程 2.工程名不可有特殊字符或空格,可以有字母.数字.下划线 2.编译器设置里勾选-g(产生调试符号) 3.重新编译项目(如果之前编译过了) 4.调试器设置 > Default & ...
- 【大数据 Spark】利用电影观看记录数据,进行电影推荐
利用电影观看记录数据,进行电影推荐. 目录 利用电影观看记录数据,进行电影推荐. 准备 1.任务描述: 2.数据下载 3.部分数据展示 实操 1.设置输入输出路径 2.配置spark 3.读取Rati ...
- vs每次生成都全部编译的问题
最近vs每次生成都会编译整个工程,经查找为.qrc中的资源路径不存在导致,删除路径后问题解决. 原文来自微信公众号"程序员成长日志",已经工作的程序员朋友可以关注下,分享日常工作中 ...
- 存储过程——公用表表达式(CTE)
目录 0. 背景说明 1. 定义及语法细节 1.1 基本定义 1.2 基本语法 1.3 多个CTE同时声明 1.4 CTE嵌套使用 2. CTE递归查询 2.1 简介 2.2 准备工作 2.3 计算每 ...
- docker build报错
docker build 遇到问题 "can not stat ... APPData\Local\Application Data" 解决方法:
- 切片原型[start:stop:step]
切片操作符在Python中的原型是 [start:stop:step] 步长值:默认是一个接着一个切取,如果为2,则表示进行隔一取一操作.步长值为正时表示从左向右取,如果为负,则表示从右向左取.步长值 ...