当前位置: 首页 > article >正文

21. 【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--补充--自动添加角色可访问接口

上一篇文章我们一起编写了自动添加接口地址,这一篇文章我们补充简易权限中的自动添加角色可访问接口。

一 实现

首先,我们Initialization文件夹下新建AddRolePath类,这个类用于初始化数据库中SysRoleUrl表,代码如下:

using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SporeAccounting.Controllers;
using SporeAccounting.Models;
using SporeAccounting.Server.Interface;

namespace SporeAccounting.Initialization;

/// <summary>
/// 添加角色路径
/// </summary>
public static class AddRolePath
{
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="serviceProvider"></param>
    public static void Init(IServiceProvider serviceProvider)
    {
        using (var scope = serviceProvider.CreateScope())
        {
            var sysRoleUrlService = scope.ServiceProvider.GetService<ISysRoleUrlServer>();
            //1. 获取所有的URL
            var sysUrlServer = scope.ServiceProvider.GetService<ISysUrlServer>();
            var urls = sysUrlServer?.Query();
            //2. 获取所有的角色
            var roleService = scope.ServiceProvider.GetService<ISysRoleServer>();
            var roles = roleService.Query();
            //3. 解析每个Controller的Authorize特性中Roles的角色
            var controllerRoles = new Dictionary<string, List<string>>();
            foreach (var controller in Assembly.GetExecutingAssembly().GetTypes()
                         .Where(t => typeof(ControllerBase).IsAssignableFrom(t)))
            {
                var authorizeAttributes = controller.GetCustomAttributes<AuthorizeAttribute>();
                foreach (var attribute in authorizeAttributes)
                {
                    var controllerName = controller.Name.Replace("Controller", "");
                    if (!controllerRoles.ContainsKey(controllerName))
                    {
                        controllerRoles[controllerName] = new List<string>();
                    }

                    controllerRoles[controllerName].AddRange(attribute.Roles.Split(','));
                }
            }

            List<SysRoleUrl> sysRoleUrls = new List<SysRoleUrl>();
            //4. 解析每个Controller的Action的特性如果有AllowAnonymous则跳过,反之拼接Controller和Action生产接口地址
            foreach (var controller in Assembly.GetExecutingAssembly().GetTypes()
                         .Where(type => typeof(BaseController).IsAssignableFrom(type)))
            {
                var actions = controller.GetMethods()
                    .Where(m => m.IsPublic && !m.GetCustomAttributes<NonActionAttribute>().Any());

                foreach (var action in actions)
                {
                    if (action.GetCustomAttributes<AllowAnonymousAttribute>().Any())
                    {
                        continue;
                    }

                    var routeAttribute = controller.GetCustomAttribute<RouteAttribute>();
                    var actionRouteAttribute = action.GetCustomAttribute<RouteAttribute>();
                    if (routeAttribute == null || actionRouteAttribute == null)
                    {
                        continue;
                    }

                    var controllerRoute = routeAttribute.Template;
                    var controllerName = controller.Name.Replace("Controller", "");
                    if (controllerRoute.Contains("[controller]"))
                    {
                        controllerRoute =
                            controllerRoute.Replace("[controller]", controllerName);
                    }

                    var actionName = actionRouteAttribute.Template;
                    if (actionName.Contains("[action]"))
                    {
                        actionName = actionName.Replace("[action]", action.Name);
                    }

                    actionName = actionName.Split("/")[0];
                    var route = $"/{controllerRoute}/{actionName}".Replace("//", "/");
                    controller.Name.Replace("Controller", "");
                    foreach (var kv in controllerRoles)
                    {
                        if (kv.Key == controllerName)
                        {
                            foreach (var role in kv.Value)
                            {
                                var roleId = roles?.FirstOrDefault(x => x.RoleName == role)?.Id;
                                var urlId = urls?.FirstOrDefault(x => x.Url == route)?.Id;
                                bool isExist = sysRoleUrlService.IsExist(roleId, urlId);
                                if(isExist)
                                {
                                    continue;
                                }
                                SysRoleUrl sysRoleUrl = new SysRoleUrl()
                                {
                                    UrlId = urlId,
                                    RoleId = roleId,
                                    CreateUserId = "b47637e2-603f-4df0-abe9-88d70fa870ee"
                                };
                                sysRoleUrls.Add(sysRoleUrl);
                            }
                        }
                    }
                }
            }

            //5. 将角色id和urlid添加到SysRoleUrl表中
            sysRoleUrlService.Add(sysRoleUrls);
        }
    }
}

这段代码实现了动态为系统中的角色分配 API 路径的功能。通过反射获取当前程序集的所有控制器及其方法,解析其特性并提取路径和角色信息,然后将这些信息与数据库中的已有角色和路径数据进行匹配,生成角色与路径的映射,并最终存储到数据库表中。代码的入口是静态类 AddRolePathInit 方法,它接受一个 IServiceProvider 参数,用于获取依赖服务。首先,代码通过创建依赖注入的作用域,获取 ISysRoleUrlServerISysUrlServerISysRoleServer 三个服务实例,分别用于管理角色与路径的关联、查询系统路径和查询角色数据。然后,代码调用相关方法查询所有路径和角色的信息,为后续操作提供基础数据。
接着,通过反射机制遍历当前程序集中的所有控制器类型,筛选出继承自 ControllerBase 的类型,并提取其 AuthorizeAttribute 特性中的 Roles 信息,记录在一个字典中,字典的键是控制器的名称(去除 “Controller” 后缀),值是控制器对应的角色列表。随后,代码进一步解析控制器中每个公开方法的路径信息,方法路径通过读取控制器和方法的 RouteAttribute 特性来拼接而成,同时会跳过带有 AllowAnonymous 特性的方法,以确保仅处理需要授权的路径。解析出的路径与控制器角色信息进行匹配,生成角色和路径的映射。
在生成角色与路径的映射关系时,代码会通过调用 sysRoleUrlService.IsExist 检查映射是否已经存在,以避免重复插入。对于不存在的映射,创建新的 SysRoleUrl 实例,设置其 RoleIdUrlIdCreateUserId 属性,并将其添加到集合中。最后,调用 sysRoleUrlService.Add 方法,将所有新的映射批量写入数据库,从而完成初始化操作。这段代码的实现提供了一种动态、自动化的方式管理角色和 API 路径的关联,既减少了手动配置的繁琐,又提升了系统的灵活性和可维护性。

二、总结

本文通过 AddRolePath 类实现了动态分配角色与接口路径的功能。代码利用反射获取控制器及其方法,解析 AuthorizeRoute 特性,提取路径和角色信息,生成映射关系并存储到数据库中。此方法减少了手动配置的繁琐,提高了权限管理的自动化和灵活性,为系统提供了高效的权限初始化方案。


http://www.kler.cn/a/459328.html

相关文章:

  • Unity WebGL 部署IIS
  • SQL 实战:基于经纬度的距离计算与位置查询
  • 爬虫后的数据处理与使用(处理篇)
  • 数据结构(Java)——链表
  • gala-gopher
  • 在Windows10下安装Docker WSL 2 桌面版
  • 基于python大数据的图书销售系统
  • Flutter:打包apk,详细图文介绍
  • QT-----------GUI程序设计基础
  • 基于Arduino的音乐喷泉设计(论文+源码)
  • echarts:5、树状图
  • C++类与对象(三)-- 再谈构造函数(细嗦初始化列表)、static成员
  • 多进程并发执行,多线程并发服务器
  • Redis中的数据类型
  • 数据结构与算法学习笔记----约数
  • 群落生态学研究进展▌Hmsc包对于群落生态学假说的解读、Hmsc包开展单物种和多物种分析的技术细节及Hmsc包的实际应用
  • CPO-CNN-GRU-Attention、CNN-GRU-Attention、CPO-CNN-GRU、CNN-GRU四模型多变量时序预测对比
  • 基于Golang的博客系统的设计与实现
  • 【最新】17个一站式数据集成平台案例PPT下载(Apache SeaTunnel )
  • 简易CPU设计入门:本系统中的通用寄存器(三)