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

Admin.NET开源版微服务改造记录

Admin.NET开源版微服务改造记录

将Admin.NET.Core项目拆分成两个项目:Admin.NET.Common,Admin.NET.Core

Admin.NET.Common放基础工具类

Admin.NET.Core放框架核心类库

AspireApp.AppHost中的AppHost.cs配置:

using Aspire.Hosting;
using Aspire.Hosting.Dapr;
using AspireApp.AppHost;var builder = DistributedApplication.CreateBuilder(args);var postgresQL = builder.AddPostgres("postgresQL").WithImage("ankane/pgvector").WithImageTag("latest").WithLifetime(ContainerLifetime.Persistent).WithHealthCheck().WithPgWeb();
var postgres = postgresQL.AddDatabase("postgres");
var postgres2 = postgresQL.AddDatabase("postgres2");//var redis = builder.AddRedis("redis").WithLifetime(ContainerLifetime.Persistent)
//                    .WithHealthCheck()
//                    .WithRedisCommander();// 使用 RabbitMQ 作为 Pub/Sub 组件
//var rabbitmq = builder.AddRabbitMQ("rabbitmq")
//                        .WithLifetime(ContainerLifetime.Persistent)
//                        .WithHealthCheck()
//                        .WithManagementPlugin();// 1. 定义共享目录的绝对路径(建议指向 admin-net-core 的实际目录或独立的 shared 目录)
var uploadPath = Path.GetFullPath("../Admin.NET/Admin.NET.Core/wwwroot/upload");// 确保目录存在
if (!Directory.Exists(uploadPath))
{Directory.CreateDirectory(uploadPath);
}// Admin.NET.Core 使用 Furion 的 Knife4j UI,不使用 Aspire 的 Swagger UI
var core = builder.AddProject<Projects.Admin_NET_Core>("admin-net-core").WithReference(postgres).WaitFor(postgres).WithSwaggerUI();var baseApi = builder.AddProject<Projects.Base>("base").WithReference(postgres2).WithSwaggerUI().WithReference(core).WaitFor(postgres2).WaitFor(core);var yarp = builder.AddProject<Projects.AspireApp_Yarp>("aspireapp-yarp").WithEndpoint( port: 5008, scheme: "http", name: "yarp-http")    // 指定唯一名称.WithEndpoint( port: 7008, scheme: "https", name: "yarp-https") // 指定唯一名称.WithReference(core).WithReference(baseApi).WaitFor(core).WaitFor(baseApi);//var frontend = builder.AddNodeApp(
//       "frontend",
//       scriptPath: "scripts/run-pnpm.cjs",
//       workingDirectory: "../Web",
//       args: new[] { "dev" }
//   )
//   .WithReference(yarp)
//   .WaitFor(yarp);builder.Build().Run();

AIP网关:AspireApp.Yarp

Program.cs

var builder = WebApplication.CreateBuilder(args);builder.AddServiceDefaults();
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")).AddServiceDiscoveryDestinationResolver();var app = builder.Build();app.MapDefaultEndpoints();
app.MapReverseProxy();app.MapGet("/", () => "Hello World!");app.Run();

appsettings.json

{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*","ReverseProxy": {"Routes": {"core": {"ClusterId": "core","Match": {"Path": "/core/{**remainder}"},"Transforms": [{ "PathRemovePrefix": "/core" },{ "PathPrefix": "/" },{ "RequestHeaderOriginalHost": "true" }]},"base": {"ClusterId": "base","Match": {"Path": "/base/{**remainder}"},"Transforms": [{ "PathRemovePrefix": "/base" },{ "PathPrefix": "/" },{ "RequestHeaderOriginalHost": "true" }]}},"Clusters": {"core": {"Destinations": {"base_destination": {"Address": "http+https://admin-net-core"}}},"base": {"Destinations": {"base_destination": {"Address": "http+https://base"}}}}}
}

业务项目(base项目)调用核心项目(core项目)的方法

我们使用Refit来服务调用

在base项目中的Startup.cs中

        // 注册 JwtTokenHandler - 用于自动添加 JWT Token 到 Refit 请求services.AddTransient<JwtTokenHandler>();// 配置 Refit 客户端并添加 JWT Token 处理器//系统配置services.AddRefitClient<IConfigService>(refitSettings).ConfigureHttpClient(c => c.BaseAddress = new("https+http://admin-net-core")).AddHttpMessageHandler<JwtTokenHandler>();//系统菜单     services.AddRefitClient<IMenuService>(refitSettings).ConfigureHttpClient(c => c.BaseAddress = new("https+http://admin-net-core")).AddHttpMessageHandler<JwtTokenHandler>();//组织机构services.AddRefitClient<IOrgService>(refitSettings).ConfigureHttpClient(c => c.BaseAddress = new("https+http://admin-net-core")).AddHttpMessageHandler<JwtTokenHandler>();//文件services.AddRefitClient<IFileService>(refitSettings).ConfigureHttpClient(c => c.BaseAddress = new("https+http://admin-net-core")).AddHttpMessageHandler<JwtTokenHandler>();services.AddRefitClient<ITest>(refitSettings).ConfigureHttpClient(c => c.BaseAddress = new("https+http://apiservice")).AddHttpMessageHandler<JwtTokenHandler>();

其中最重要的权限接口调用

using Refit;
using GetAttribute = Refit.GetAttribute;
namespace Base.Rest;public interface IMenuService
{[Get("/api/sysMenu/getOwnBtnPermList")]Task<List<string>> GetOwnBtnPermList();[Get("/api/sysMenu/getAllBtnPermList")]Task<List<string>> GetAllBtnPermList();
}

修改base项目的权限验证方法JwtHandler.cs

IConfigService IMenuService 就是我们定义的Refit接口,这样,每次权限验证就会调用core项目的API接口

using Admin.NET.Core;
using Admin.NET.Core.Service;
using Base.Rest;
using Furion;
using Furion.Authorization;
using Furion.DataEncryption;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;namespace Admin.NET.Application;public class JwtHandler : AppAuthorizeHandler
{private readonly SysCacheService _sysCacheService = App.GetRequiredService<SysCacheService>();private readonly IConfigService _sysConfigService = App.GetRequiredService<IConfigService>();private static readonly IMenuService SysMenuService = App.GetRequiredService<IMenuService>();/// <summary>/// 自动刷新Token/// </summary>/// <param name="context"></param>/// <param name="httpContext"></param>/// <returns></returns>public override async Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext){// 若当前账号存在黑名单中则授权失败if (_sysCacheService.ExistKey($"{CacheConst.KeyBlacklist}{context.User.FindFirst(ClaimConst.UserId)?.Value}")){context.Fail();context.GetCurrentHttpContext().SignoutToSwagger();return;}var tokenExpire = await _sysConfigService.GetTokenExpire();var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(), tokenExpire.Result, refreshTokenExpire.Result)){await AuthorizeHandleAsync(context);}else{context.Fail(); // 授权失败var currentHttpContext = context.GetCurrentHttpContext();if (currentHttpContext == null) return;// 跳过由于 SignatureAuthentication 引发的失败if (currentHttpContext.Items.ContainsKey(SignatureAuthenticationDefaults.AuthenticateFailMsgKey)) return;currentHttpContext.SignoutToSwagger();}}public override async Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext){// 已自动验证 Jwt Token 有效性return await CheckAuthorizeAsync(httpContext);}/// <summary>/// 权限校验核心逻辑/// </summary>/// <param name="httpContext"></param>/// <returns></returns>private static async Task<bool> CheckAuthorizeAsync(DefaultHttpContext httpContext){// 登录模式判断PC、APPif (App.User.FindFirst(ClaimConst.LoginMode)?.Value == ((int)LoginModeEnum.APP).ToString())return true;// 排除超管if (App.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString())return true;// 路由名称var routeName = httpContext.Request.Path.StartsWithSegments("/api")? httpContext.Request.Path.Value![5..].Replace("/", ":"): httpContext.Request.Path.Value![1..].Replace("/", ":");// 获取用户拥有按钮权限集合var ownBtnPermList = await SysMenuService.GetOwnBtnPermList();if (ownBtnPermList.Exists(u => routeName.Equals(u, StringComparison.CurrentCultureIgnoreCase)))return true;// 获取系统所有按钮权限集合var allBtnPermList = await SysMenuService.GetAllBtnPermList();return allBtnPermList.TrueForAll(u => !routeName.Equals(u, StringComparison.CurrentCultureIgnoreCase));}
}

项目地址

AspireApp: Admin.NET微服务版

Admin.NET: 🔥🔥🔥 Admin.NET 基于 .NET8/10 (Furion/SqlSugar) 实现的通用权限开发框架,前端采用 Vue3/Element-plus,代码简洁、易扩展。整合最新技术,模块插件式开发,前后端分离,开箱即用。集成多租户、缓存、数据校验、鉴权、事件总线、动态API、通讯、远程请求、任务调度、打印等众多黑科技。让开发更简单、更通用、更流行!

http://www.jsqmd.com/news/378501/

相关文章:

  • 百元保费百万保额!首信保险代理联合泰康在线推出“安心保百万重疾险” - 包罗万闻
  • 2026年口碑好的桑蚕丝绒/混纺丝绒推荐几家可靠供应商参考 - 品牌宣传支持者
  • 2026年国内枕式包装机品牌TOP5:规模实力优选榜单+数据背书 - 深度智识库
  • 2026食用面碱头部企业推荐:品质与口碑兼具,型煤淀粉/纸袋淀粉/锅包肉专用粉/复合淀粉,食用面碱供应商怎么选择 - 品牌推荐师
  • 构建高效系统:IO操作扩展技术全解析
  • 深耕专业,引领行业!首信保险代理获任广东保险中介行业协会第四届保险代理专业委员会副主任委员单位 - 包罗万闻
  • 瑞祥商联卡闲置别浪费!靠谱的回收方式,可可收亲测好用 - 可可收
  • 新春臻选健康好物,iHerb守护全家日常美好 - 博客万
  • 2026年苏州加热盘生产厂排名,如何选择靠谱品牌 - mypinpai
  • Nodejs+vue+ElementUI的美食商城交流平台的设计与实现
  • 如何选择适配复杂场景的平台?2026年项目集管理平台评测与推荐,直击数据孤岛痛点 - 品牌推荐
  • 如何选择适配敏捷与瀑布的项目工具?2026年project管理系统全面评测与推荐 - 品牌推荐
  • 提升SEO效果的长尾关键词运用与应用策略解析
  • 2026年食品包装机厂家推荐:食品包装机服务商权威测评与深度解析 - 深度智识库
  • 专科生必看!碾压级的降AI率平台 —— 千笔·降AI率助手
  • Nodejs+vue+ElementUI的校园电影网站的设计与实现express-mysql
  • 2026年项目集管理工具推荐:大型企业战略级场景深度评测,解决多项目协同与资源统筹痛点 - 品牌推荐
  • 实测对比后一键生成论文工具 千笔写作工具 VS 锐智 AI 本科生必备
  • 2026年专业读写台品牌排名,佳视路读写台对坐姿有帮助吗 - myqiye
  • Nodejs+vue+ElementUI的校园兼职系统的设计与实现
  • 2026年广东地区法兰型分度器实力厂家排名,推荐性价比高的品牌 - 工业品牌热点
  • Nodejs+vue+ElementUI的旅游预算线路推荐系统express-mysql
  • 探讨杰家的板材厂,选择哪家更有性价比 - 工业推荐榜
  • Nodejs+vue+ElementUI的母婴用品购物商城 积分平台设计与实现express-mysql
  • Nodejs+vue+ElementUI的校园教室预约综合管理系统express-mysql
  • 分析杰家板材厂,值得推荐的板材厂家有哪些? - 工业品牌热点
  • Nodejs+vue+ElementUI的小说在线阅读销售平台express-mysql
  • 2026年支付宝立减金套装回收攻略——盘活闲置权益,正规回收不浪费 - 可可收
  • 聊聊实力强的嘉陈商贸,揭秘其靠谱的食堂餐桌椅定制服务及价格 - 工业品网
  • 数据前瞻:清洁室二次配工程2032年市场规模将达702.2亿元,产业潜力持续释放