权限做到"菜单和按钮"就够了吗?企业里真正难的是第四层
几乎每个后台框架都说自己有 RBAC。打开一看,确实有:用户、角色、菜单,勾一勾就授权了。
但进了企业项目,需求往往会多出一层:
"销售总监能看到全公司客户,区域经理只能看本区域,销售只能看自己跟进的------同一个列表页面。"
这一层叫数据权限 。它和菜单权限的区别是:菜单权限决定"能不能进这个页面",数据权限决定"进了页面能看到哪几行"。很多框架做到第三层就止步了,剩下的交给业务代码------于是每个列表查询里都散落着 if (role == 区域经理) sql += "..."。
一、QuickBlue 的四层权限模型
QuickBlue(原生 AI 微服务快速开发平台)在 QuickBlue-system 服务(8081)里把权限拆成了四层:
| 层级 | 承担者 | 典型入口 |
|---|---|---|
| 认证 | Sa-Token 1.44.0 | AuthController / SecureLoginController,含验证码与密码失败锁定 |
| 功能权限(菜单/按钮) | RBAC | NavMenuController(菜单/路由/按钮)、AuthRoleMenuController |
| 授权关系 | 角色-人员绑定 | AuthRoleController / AuthRoleStaffController / StaffController |
| 数据权限(行级) | @DataPermission 注解 + MyBatis 拦截器 |
DataPermissionConfigController / AuthRoleDataPermissionController |
前三层是行业标配,第四层才是拉开差距的地方。
二、认证这层,配置是明牌
nacos_config/common/sa-token-common.yaml 里全部可查、可改:
yaml
sa-token:
token-name: Authorization
token-prefix: Bearer
is-read-header: true # 走 Header,天然适配前后端分离与小程序
is-concurrent: true # 允许并发登录
timeout: 2592000 # 30 天
active-timeout: 1800 # 30 分钟无操作失效
sa-token-dao: spring-redis # Token 落 Redis,多实例共享
Token 存 Redis 意味着网关 + 5 个微服务任何一台实例都能验票,不需要 session 粘滞,这是微服务能横向扩展的前提。
三、数据权限:一个注解 + 一个拦截器
QuickBlue 的做法很直接------不在业务代码里写 if,而是让框架在 SQL 执行前自动追加条件。
核心是两个东西:
1)@DataPermission 注解 (system/annotation/DataPermission.java),打在 DAO 查询方法上:
java
@DataPermission(configCode = "EMPLOYEE", selfScopeColumn = "create_user_id")
List<StaffVO> selectStaffList(StaffQueryForm form);
注解参数把它做成了一个可配置的小 DSL:
| 参数 | 作用 |
|---|---|
configCode |
数据权限配置编码,对应库中配置记录,新增业务模块只需插一条配置,不改代码 |
whereInType |
范围匹配方式,支持 EMPLOYEE 等内置类型与 CUSTOM_STRATEGY |
joinSqlImplClazz |
自定义策略类(继承 AbstractDataPermissionStrategy),复杂场景自己拼 SQL |
paramName / whereIndex |
按参数差异化控制 / 指定条件插入位置 |
joinSql |
关联子查询 |
selfScopeColumn |
"仅本人"时依据的字段,默认 create_user_id,可换成 manager_id 等 |
2)MyBatisDataPermissionPlugin (system/plugin/),一个标准 MyBatis Executor.query 拦截器:在执行前拿到 BoundSql,根据当前用户的角色数据权限配置,自动拼接范围条件后再放行。
业务代码里因此没有一行权限判断------权限逻辑集中在一处,改策略不需要翻遍所有查询。
配合 DataPermissionTypeEnum,开箱就有 7 种范围:
java
ALL(1, "全部数据权限"), CUSTOM(2, "自定义数据权限"), DEPT(3, "本部门数据权限"),
DEPT_AND_CHILD(4, "本部门及以下数据权限"), ONLY_SELF(5, "仅本人数据权限"),
NOTICE(6, "通知权限"), EMPLOYEE(7, "员工管理")
"本部门及以下"这种带递归的需求,是数据权限里最容易写错也最容易拖慢查询的一种,这里直接是枚举里的一项。
四、为什么这件事对 AI 应用尤其重要
这是 QuickBlue 与其他后台框架差异最大的地方:AI 能力长在这套权限边界之内。
企业做 RAG 知识库时最大的顾虑不是"AI 答得准不准",而是"AI 会不会把 A 部门的合同答给 B 部门的人"。如果权限只到菜单层,那么知识库检索就是一个绕过权限的后门;而当数据权限在 SQL 层统一收敛,AI 检索走同一套数据访问路径,越权问题在数据出口就被挡住了------不用在每个 AI 接口里再手写一遍权限判断。
一句话:让 AI 懂业务的前提,是让 AI 守规矩。
五、配套的可审计性
权限之外还有可追溯:LoginRecordController 记录登录审计,AuditLogController 配合 @AuditLog 切面做全链路操作审计(异步落库,含 IP 归属地)。谁能看什么、谁改了什么,都有据可查------这是等保与内控环节最常被问到的两件事。
六、上手路径
- 在线体验:ide.budaos.com
- (账号
admin,密码nq963369#),可直接操作系统管理、角色授权、数据权限配置 - 本地搭建:README 快速搭建章节,向导式安装 10 分钟完成
- 接口文档:启动后访问
http://localhost:8080/doc.html,QuickBlue-system分组下即为认证 / RBAC / 组织 / 岗位 / 数据权限全部接口
菜单权限决定能进哪扇门,数据权限决定能看哪些东西。企业敢把业务放上去,靠的是后者。