Skip to content
.NET 开发者指北.NET 开发者指北
CMS
.NET指北
FreeKit
Docker
关于
博客
github icon
    • 开发起步
      • Newtonsoft.Json基础问题
        • 依赖注入scrutor
          • 认证与授权
            • 获取控制器及方法特性标签
              • LinCmsAuthorizeAttribute 是什么
                • Controller
                  • 测试类获取方法上的特定标签
                    • 方法结果
                      • 获取控制器上特性标签
                        • Controller 结果
                          • 参考
                            • 开源地址
                            • 认证鉴权状态
                              • 全局敏感词处理
                                • GitHub第三方授权登录
                                  • QQ第三方授权登录
                                    • CAP实现EventBus
                                      • Scriban 模板语言

                                      获取控制器及方法特性标签

                                      calendar icon2022年6月2日timer icon大约 3 分钟word icon约 1023 字

                                      此页内容
                                      • LinCmsAuthorizeAttribute 是什么
                                      • Controller
                                      • 测试类获取方法上的特定标签
                                      • 方法结果
                                      • 获取控制器上特性标签
                                      • Controller 结果
                                      • 参考
                                      • 开源地址

                                      # 获取控制器及方法特性标签

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

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

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

                                      # LinCmsAuthorizeAttribute 是什么

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

                                      • https://www.cnblogs.com/RainingNight/p/dynamic-authorization-in-aspnetcore.htmlopen in new window

                                      当然,这个只是部分代码,完整代码请查看最下方开源地址,其中 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}\"";
                                          }
                                      }
                                      
                                      1
                                      2
                                      3
                                      4
                                      5
                                      6
                                      7
                                      8
                                      9
                                      10
                                      11
                                      12
                                      13
                                      14
                                      15
                                      16
                                      17
                                      18
                                      19
                                      20
                                      21
                                      22
                                      23
                                      24
                                      25
                                      26
                                      27
                                      28
                                      29
                                      30
                                      31
                                      32
                                      33
                                      34
                                      35
                                      36
                                      37
                                      38
                                      39

                                      # Controller

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

                                      [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);
                                          }
                                      }
                                      
                                      1
                                      2
                                      3
                                      4
                                      5
                                      6
                                      7
                                      8
                                      9
                                      10
                                      11
                                      12
                                      13
                                      14
                                      15
                                      16
                                      17
                                      18
                                      19
                                      20
                                      21
                                      22
                                      23
                                      24
                                      25
                                      26
                                      27
                                      28
                                      29
                                      30
                                      31
                                      32
                                      33

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

                                      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());
                                                      }
                                                  }
                                              }
                                          });
                                      }
                                      
                                      1
                                      2
                                      3
                                      4
                                      5
                                      6
                                      7
                                      8
                                      9
                                      10
                                      11
                                      12
                                      13
                                      14
                                      15
                                      16
                                      17
                                      18
                                      19
                                      20

                                      # 方法结果

                                      可在输出文本中查看,正是我们想要的东西,最后一行,是其他 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:"
                                      
                                      
                                      1
                                      2
                                      3
                                      4
                                      5

                                      # 获取控制器上特性标签

                                      /// <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());
                                              }
                                          });
                                      }
                                      
                                      1
                                      2
                                      3
                                      4
                                      5
                                      6
                                      7
                                      8
                                      9
                                      10
                                      11
                                      12
                                      13
                                      14
                                      15
                                      16
                                      17
                                      18
                                      19

                                      # Controller 结果

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

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

                                      此时 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
                                      {
                                          ...
                                      }
                                      
                                      1
                                      2
                                      3
                                      4
                                      5

                                      # 参考

                                      • c# – 如何在 asp. net core rc2 中获取控制器的自定义属性 https://codeday.me/bug/20181207/453278.htmlopen in new window

                                      # 开源地址

                                      • github.com/luoyunchong/lin-cms-dotnetcore
                                      edit icon在 GitHub 上编辑此页open in new window
                                      上次编辑于: 2022/9/13 11:34:29
                                      贡献者: igeekfan,igeekfan
                                      上一页
                                      认证与授权
                                      下一页
                                      认证鉴权状态
                                      MIT Licensed | Copyright © 2021-present luoyunchong
                                      苏ICP备16046457号-1

                                      该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。

                                      详情