generated from youfool-project/youfool-prj-springboot3-template
12 KiB
12 KiB
OARMS 权限体系设计与实现计划
目标
基于 PRD 第三章"角色权限"定义,设计并实现完整的 RBAC + 数据权限体系,覆盖后端认证/鉴权 + 前端路由/按钮控制。
PRD 角色定义
| 角色 | 角色代码 | 操作范围 | 数据范围 |
|---|---|---|---|
| 市局广告监管人员 | CITY_SUPERVISOR |
全模块读写 | 全市数据 |
| 区局广告监管人员 | DISTRICT_SUPERVISOR |
监控/取证/规则只读 | 本辖区数据 |
| 广告大屏运营商 | OPERATOR |
大屏维护/录屏查看 | 本公司大屏数据 |
当前状态
| 组件 | 现状 | 缺失 |
|---|---|---|
| Sa-Token 框架 | 已集成,拦截器已配置 | 仅 checkLogin,无角色/权限校验 |
| LoginController | 硬编码 userId,admin 权限 | 无数据库校验 |
| StpInterfaceImpl | 返回空列表 | 未对接数据库 |
| UserBaseServiceImpl | login() 返回 null | 未实现 |
| 数据库 | 无用户/角色表 | 需建表 |
| 前端路由 | 仅 admin/guest | 需增加 3 个角色 |
| 前端权限守卫 | admin 全通 | 需角色过滤 |
实现阶段(7 个 Phase)
Phase 1:数据库设计 — 用户/角色/权限表(DDL)
在 OARMS schema 下创建系统管理相关表,表前缀 sys_。
表设计:
1.1 SYS_USER 用户表
| 列名 | 类型 | 说明 |
|---|---|---|
| ID | VARCHAR(32) PK | UUID |
| USERNAME | VARCHAR(50) NOT NULL UNIQUE | 登录用户名 |
| PASSWORD | VARCHAR(100) NOT NULL | BCrypt 加密密码 |
| REAL_NAME | VARCHAR(50) | 真实姓名 |
| PHONE | VARCHAR(20) | 联系电话 |
| ORG_NAME | VARCHAR(100) | 所属单位 |
| DISTRICT_CODE | VARCHAR(20) | 所属区域编码(区局/运营商用) |
| STATUS | TINYINT DEFAULT 1 | 1=正常 0=停用 |
| + SuperEntity 审计字段 | createBy/createTime/updateBy/updateTime/updateName |
1.2 SYS_ROLE 角色表
| 列名 | 类型 | 说明 |
|---|---|---|
| ID | VARCHAR(32) PK | UUID |
| ROLE_CODE | VARCHAR(30) NOT NULL UNIQUE | 角色编码(CITY_SUPERVISOR 等) |
| ROLE_NAME | VARCHAR(50) NOT NULL | 角色显示名 |
| DESCRIPTION | VARCHAR(200) | 描述 |
| STATUS | TINYINT DEFAULT 1 | 1=正常 0=停用 |
| + SuperEntity 审计字段 |
1.3 SYS_USER_ROLE 用户角色关联表
| 列名 | 类型 | 说明 |
|---|---|---|
| ID | VARCHAR(32) PK | UUID |
| USER_ID | VARCHAR(32) NOT NULL | 关联 SYS_USER.ID |
| ROLE_ID | VARCHAR(32) NOT NULL | 关联 SYS_ROLE.ID |
| + createBy/createTime |
1.4 SYS_PERMISSION 权限表(操作权限码)
| 列名 | 类型 | 说明 |
|---|---|---|
| ID | VARCHAR(32) PK | UUID |
| PERM_CODE | VARCHAR(50) NOT NULL UNIQUE | 权限编码(如 screen:view、evidence:create) |
| PERM_NAME | VARCHAR(100) NOT NULL | 权限名称 |
| MODULE | VARCHAR(30) | 所属模块(BS/LB/AM/MR/CW) |
| + SuperEntity 审计字段 |
1.5 SYS_ROLE_PERMISSION 角色权限关联表
| 列名 | 类型 | 说明 |
|---|---|---|
| ID | VARCHAR(32) PK | UUID |
| ROLE_ID | VARCHAR(32) NOT NULL | 关联 SYS_ROLE.ID |
| PERM_ID | VARCHAR(32) NOT NULL | 关联 SYS_PERMISSION.ID |
| + createBy/createTime |
1.6 初始数据
3 条角色 + 3 条管理员用户(各角色 1 个)+ 权限码 + 角色权限映射。
权限码清单(按模块):
| 权限码 | 说明 | 市局 | 区局 | 运营商 |
|---|---|---|---|---|
screen:view |
查看大屏 | Y | Y(本辖区) | Y(本公司) |
screen:create |
新增大屏 | Y | N | Y(本公司) |
screen:edit |
编辑大屏 | Y | N | Y(本公司) |
screen:remove |
删除大屏 | Y | N | N |
screen:export |
导出大屏 | Y | Y(本辖区) | N |
law:view |
查看法律条款 | Y | Y | Y |
law:create |
新增条款 | Y | N | N |
law:edit |
编辑条款 | Y | N | N |
law:remove |
删除条款 | Y | N | N |
monitoring-rule:view |
查看规则 | Y | Y | N |
monitoring-rule:create |
新增规则 | Y | N | N |
monitoring-rule:edit |
编辑规则 | Y | N | N |
monitoring-rule:remove |
删除规则 | Y | N | N |
recording-config:view |
查看录屏配置 | Y | Y(本辖区) | Y(本公司) |
recording-config:create |
新增录屏配置 | Y | N | N |
recording-config:edit |
编辑录屏配置 | Y | N | N |
recording-task:view |
查看录屏任务 | Y | Y(本辖区) | Y(本公司) |
monitor-record:view |
查看监控记录 | Y | Y(本辖区) | N |
monitor-record:handle |
处理监控 | Y | Y(本辖区) | N |
evidence:view |
查看取证 | Y | Y(本辖区) | N |
evidence:create |
固化取证 | Y | Y(本辖区) | N |
evidence-relation:view |
查看规则关联 | Y | Y(本辖区) | N |
evidence-relation:bind |
关联规则 | Y | Y(本辖区) | N |
monitoring-clue:view |
查看线索 | Y | Y(本辖区) | N |
monitoring-clue:create |
生成线索 | Y | Y(本辖区) | N |
clue-transfer:view |
查看转办 | Y | Y(本辖区) | N |
clue-transfer:create |
发起转办 | Y | Y(本辖区) | N |
数据权限(不在权限码中,在角色级别控制):
| 角色 | 数据范围 | 实现方式 |
|---|---|---|
| CITY_SUPERVISOR | 全市 | 无 SQL 过滤 |
| DISTRICT_SUPERVISOR | 本辖区 | 按 district_code 过滤 |
| OPERATOR | 本公司 | 按 org_name 过滤 |
阶段输出: DDL SQL 文件 + 初始数据 SQL
状态: ✅ 完成
Phase 2:后端 Entity/Mapper 层
按项目约定创建:
modules/system/
├── entity/
│ ├── SysUserEntity.java
│ ├── SysRoleEntity.java
│ ├── SysUserRoleEntity.java
│ ├── SysPermissionEntity.java
│ ├── SysRolePermissionEntity.java
│ ├── query/
│ │ └── SysUserQuery.java
│ └── vo/
│ ├── SysUserVO.java
│ └── LoginUserVO.java # 登录后返回给前端的信息
├── mapper/
│ ├── SysUserMapper.java
│ ├── SysRoleMapper.java
│ ├── SysUserRoleMapper.java
│ ├── SysPermissionMapper.java
│ └── SysRolePermissionMapper.java
└── service/
├── ISysUserService.java
├── ISysRoleService.java
└── impl/
├── SysUserServiceImpl.java
└── SysRoleServiceImpl.java
关键方法:
SysUserMapper.findByUsername(username)— 登录查询SysRoleMapper.selectByUserId(userId)— 查用户角色SysPermissionMapper.selectByUserId(userId)— 查用户权限码SysPermissionMapper.selectByRoleCode(roleCode)— 查角色权限
LoginUserVO 返回给前端的信息:
{
"userId": "...",
"username": "...",
"realName": "...",
"roles": ["CITY_SUPERVISOR"],
"roleNames": ["市局广告监管人员"],
"permissions": ["screen:view", "screen:create", ...],
"districtCode": null,
"orgName": "广州市市场监督管理局"
}
状态: ✅ 完成
Phase 3:认证流程实现(LoginController + StpInterfaceImpl)
3.1 LoginController 改造
POST /user/auth/login
→ SysUserService.findByUsername(username)
→ BCrypt.checkPassword(password, user.password)
→ StpUtil.login(user.id)
→ session.set(USER_KEY, LoginUserVO)
→ response.setHeader("satoken", token)
→ return RestResult.ok(LoginUserVO)
3.2 StpInterfaceImpl 实现
getPermissionList(loginId) → SysPermissionMapper.selectByUserId(loginId)
getRoleList(loginId) → SysRoleMapper.selectRoleCodesByUserId(loginId)
3.3 /user/auth/login/info 改造
返回 LoginUserVO(含 roles + permissions + districtCode + orgName)。
3.4 UserBaseServiceImpl 完善
- login() 对接 SysUserService
- getCurrentUser() 从 session 取 LoginUserVO
状态: ✅ 完成
Phase 4:鉴权拦截器 + 数据权限
4.1 SpringMvcConfig 权限路由
按模块配置权限检查:
SaRouter.match("/api/screen/**", r -> StpUtil.checkLogin());
SaRouter.match("/api/monitoring-rule/**", r -> {
StpUtil.checkLogin();
// 具体 CRUD 方法用注解控制
});
// ... 其余模块类似
4.2 Controller 方法级权限注解
在需要权限控制的 Controller 方法上加:
@SaCheckPermission("screen:create")
@PostMapping("save")
public RestResult<?> save(...) { ... }
@SaCheckPermission("screen:remove")
@PostMapping("remove")
public RestResult<?> remove(...) { ... }
4.3 数据权限过滤
在 Service 层的查询方法中,根据当前用户的角色过滤数据:
- CITY_SUPERVISOR: 不过滤
- DISTRICT_SUPERVISOR: 在 Query 中追加
district_code = currentUser.districtCode - OPERATOR: 在 Query 中追加
org_name = currentUser.orgName
实现方式:在 Service 中获取当前用户,动态拼装查询条件。
注意:数据权限需要修改现有 10 个模块的 Service 查询方法,影响范围较大。建议先实现 Phase 1-3 的认证和操作权限,Phase 4 数据权限单独迭代。
实际实施:
- 创建
DataScopeHelper工具类(modules/system/util/),提供角色判断静态方法 - 修改 7 个 Service 的 queryList 方法,添加数据权限过滤:
- ScreenServiceImpl: queryList + exportData + getScreenOptions
- RecordingConfigServiceImpl: queryList + getConfigurableScreens
- RecordingTaskServiceImpl: queryList
- MonitorRecordServiceImpl: queryList
- EvidenceRecordServiceImpl: queryList
- MonitoringClueServiceImpl: queryList
- ClueTransferServiceImpl: queryList + queryPendingClues
- 过滤规则:
- CITY_SUPERVISOR: 不过滤(全市数据)
- DISTRICT_SUPERVISOR: 按
district = currentUser.districtCode过滤 - OPERATOR: Screen 按
operatorUnit = orgName,其他模块通过 screenId 关联 Screen 过滤
- ClueTransferServiceImpl 特殊处理:OR 条件(转办目标辖区 + 线索来源辖区)
- 跳过模块:LawClauseServiceImpl(无区域字段)、MonitoringRuleServiceImpl(复杂 scope JSON)、EvidenceRuleRelationServiceImpl(关联表)
状态: ✅ 完成
Phase 5:前端角色路由映射
5.1 定义角色常量
// src/utils/constants.js 或 src/router/roles.js
export const ROLES = {
CITY_SUPERVISOR: 'CITY_SUPERVISOR',
DISTRICT_SUPERVISOR: 'DISTRICT_SUPERVISOR',
OPERATOR: 'OPERATOR'
}
5.2 更新 routes.js 的 meta.roles
按 PRD 权限矩阵为每个业务路由分配角色:
// BS-大屏基础库 - 三个角色都能访问
meta: { roles: [ROLES.CITY_SUPERVISOR, ROLES.DISTRICT_SUPERVISOR, ROLES.OPERATOR] }
// MR-监测规则 - 市局+区局
meta: { roles: [ROLES.CITY_SUPERVISOR, ROLES.DISTRICT_SUPERVISOR] }
// CW-内容预警 - 市局+区局
meta: { roles: [ROLES.CITY_SUPERVISOR, ROLES.DISTRICT_SUPERVISOR] }
5.3 更新 permission.js
- 去掉 admin 硬编码全通逻辑
- 使用后端返回的 permissions 数组做按钮级控制
5.4 按钮级权限指令
添加 v-permission 指令,控制按钮显示:
<el-button v-permission="'screen:create'">新增</el-button>
<el-button v-permission="'screen:remove'">删除</el-button>
状态: ✅ 完成
Phase 6:用户管理接口(可选)
提供用户 CRUD 接口供后台管理使用:
POST /api/sys-user/query— 用户列表(分页)POST /api/sys-user/save— 新增用户POST /api/sys-user/update— 编辑用户POST /api/sys-user/remove— 删除用户POST /api/sys-user/reset-password— 重置密码GET /api/sys-user/role-options— 角色选项列表
前端对应的管理页面可后续迭代。
状态: pending
Phase 7:编译验证 + 端到端测试
- DDL 执行到 DM8 数据库
- 后端编译通过(
mvn compile -Dcheckstyle.skip=true) - 启动后端,验证登录流程
- 验证权限校验(无权限返回 403)
- 前端
npm run lint通过 - 前端登录后路由正确过滤
状态: ✅ 完成(BUILD SUCCESS)
实施建议
优先级排序
| 优先级 | Phase | 说明 |
|---|---|---|
| P0 必须 | Phase 1-3 | DDL + Entity/Mapper + 认证流程,使登录对接真实数据库 |
| P1 重要 | Phase 5 | 前端角色路由,使不同角色看到不同菜单 |
| P2 增强 | Phase 4 | 操作权限注解 + 数据权限过滤 |
| P3 可选 | Phase 6 | 用户管理 CRUD |
| P0 验证 | Phase 7 | 编译 + 测试 |
建议实施路径
第一轮(核心认证): Phase 1 → 2 → 3 → 7 第二轮(前端权限): Phase 5 → 7 第三轮(精细控制): Phase 4 → 6
修复决策
(实施过程中记录)