36
0
1

Easy.SmartNet_多租户后台管理系统脚手架正式上线

2026-10-22
2026-10-22
Easy.SmartNet_多租户后台管理系统脚手架正式上线
文章摘要
|

2026 年 10 月 · 原创 · 约 5 分钟读完

折腾了大半年的业余时间,我的开源项目 Easy.SmartNet 终于到了可以拿出手的状态,今天正式上线。

仓库地址:https://gitee.com/youcanhuang/easy-smartnet

一句话介绍:一套开箱即用的多租户后台管理系统脚手架,把认证、权限、租户隔离、审计、缓存这些每个业务项目都要重写一遍的横切能力下沉到框架层,上层业务只写领域逻辑。

一、为什么要造这个轮子

这几年做业务系统,几乎每个新项目开局都是同一套活:搭用户表、写登录、做权限、加租户隔离、配操作日志……这些代码在各项目间复制粘贴,改着改着就分叉了,安全细节也参差不齐。

所以我干脆把这些反复出现的横切能力做成了一个框架层产品:业务项目拿去,第一天就能站在认证闭环、RBAC、多租户隔离、审计日志之上开始写真正的业务。

二、它能做什么

  • 多租户隔离:仓储层统一注入租户过滤,业务代码零感知,天然防越权

  • 认证与会话:JWT 双令牌轮换、按用户吊销(改密/禁用/删除/强踢全设备下线)、刷新令牌一次性消费防重放

  • RBAC 权限:菜单/按钮三级资源,后端 [HasPermission] 动态策略 + 前端指令双层控制,支持部门数据范围(全部/本部门及以下/仅本部门/仅本人)

  • 完整管理模块:用户、角色、菜单、租户、部门、字典、系统配置、文件、公告、在线用户、登录/操作日志(密码字段自动脱敏)

  • 工程配套:软删除 + 审计字段、Redis 缓存(内存回退)、接口限流、Hangfire 定时任务面板、数据库启动自动建表 + 种子、MiniExcel 导入导出、SVG 验证码

三、技术栈与架构

分类

技术

后端

.NET 10 / ASP.NET Core Web API / SqlSugar ORM / MySQL

前端

Vue 3 + TypeScript + Pinia + Element Plus + Vite

架构

Clean Architecture 分层(Core / Repository / Service / Infrastructure / Framework / Api)

扩展

插件模块机制(Module 自动装载服务、控制器、建表、种子)

分层的核心是过滤器上收:多租户、软删除、数据范围这些边界条件全部收敛在仓储基类的查询构建里,业务 Service 和 Controller 里看不到一行 WHERE TenantId =——想绕过都难。

四、几个我比较满意的细节

1. 会话吊销是一个闭环,不是几个补丁

改密码、禁用账号、删除账号、管理员重置密码、踢下线——这五个动作背后是同一个机制:用户级 SecurityStamp 轮换。安全戳写进 JWT 声明,认证中间件每个请求比对,轮换瞬间全设备失效;刷新令牌做一次性消费占位,泄露了也换不出第二套会话。

2. 缓存故障时宁可拒绝,绝不放行

很多实现里 Redis 挂了黑名单就跟着失效(fail-open),已登出的令牌悄悄放行。Easy.SmartNet 对这类安全判定点做了分级:普通业务缓存降级容错,黑名单检查走严格模式——缓存不可用就明确拒绝,配合安全戳回源数据库兜底。

3. 后台作业也有"身份证"

定时任务线程没有 HTTP 上下文,租户过滤会退化成 TenantId=0,清理作业永远清不到数据。框架用系统身份作用域解决,作业代码不需要任何特殊处理。

五、质量是怎么磨出来的

上线前我自己对这个项目做了三轮安全审计,这段经历比写功能本身收获更大:

第一轮扫出 41 项缺陷:越权删除、令牌吊销漏洞、缓存熔断放行……然后按 P0 → P1 分了七批修复,每一批走完整的 PR 流程,修复后复扫确认,直到 P0/P1 全部清零。

印象最深的是一个隐蔽 bug:JWT 的入站声明映射默认会把自定义声明 tid 改写成微软标准 URI,导致超管一切正常、所有普通租户用户查询恒空——因为超管跳过租户过滤,问题被完美掩盖。最后是靠数据库通用日志抓到那条 WHERE TenantId = 0 的真实 SQL 才定位的。这类"静默失效"比崩溃可怕得多,也让我给项目补上了防回归测试。

现在的质量水位:208 个单元测试全绿,每个安全修复都带防回归用例,合并前有启动冒烟检查。

六、快速开始

git clone https://gitee.com/youcanhuang/easy-smartnet.git
# 修改 src/Easy.SmartNet.Api/appsettings.json 中的数据库连接串
cd src/Easy.SmartNet.Api && dotnet run
# 首次启动自动建库建表 + 写入种子数据
cd web && npm install && npm run dev
# 浏览器打开 http://localhost:5173,默认账号 admin / Admin@123

后端开发环境根路径即 Swagger UI,接口文档开箱即用。

七、接下来

  • 把库位管理业务做成第一个真实的业务插件,验证插件机制的完整闭环

  • 继续清理低优先级的安全与体验项

  • 补齐实时通信(SignalR)、邮件/短信抽象等常见能力

写在最后

造轮子的意义不在轮子本身——在于把"每个项目都糊一遍"的东西,认真打磨成一次做对的东西。项目刚上线,肯定还有考虑不周的地方,欢迎提 Issue、提 PR,或者单纯来聊聊多租户和权限设计的坑。

仓库:gitee.com/youcanhuang/easy-smartnet(README 里有 12 张系统界面截图)

—— 2026.10 · 于福州

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!