Files
cattleTransportation/pc-cattle-transportation/PERMISSION_MANAGEMENT_EXPLANATION.md

153 lines
4.7 KiB
Markdown
Raw Normal View History

# 权限管理机制说明
## 问题描述
用户反映:修改"12.27新增姓名"这个用户的操作权限时,超级管理员的权限也会被修改。
## 根本原因
当前系统使用的是**基于角色的权限管理RBAC - Role-Based Access Control**而不是基于用户的权限管理UBAC - User-Based Access Control
### 权限架构分析
1. **数据库表结构**
- `sys_role_menu` 表:存储角色-菜单权限关系
- `sys_user` 表:存储用户信息,包含 `roleId` 字段
- **没有** `sys_user_menu` 表:不存在用户-菜单权限关系
2. **权限分配机制**
- 权限分配基于 `roleId`角色ID
- 所有使用相同 `roleId` 的用户共享相同的权限
- 修改权限时影响整个角色,不是单个用户
3. **权限获取流程**
```java
// LoginServiceImpl.java 第124行
List<String> permissions = queryUserPermissions(user.getRoleId());
```
- 用户登录时,根据用户的 `roleId` 获取权限
- 不是根据用户的 `userId` 获取权限
## 具体案例分析
### 用户信息对比
| 用户 | 用户ID | 角色ID | 权限来源 |
|------|--------|--------|----------|
| 12.27新增姓名 | 3 | 1 | roleId=1 的权限 |
| 超级管理员 | 11 | 1 | roleId=1 的权限 |
### 权限修改影响
当修改"12.27新增姓名"的权限时:
1. 前端发送请求:`{ roleId: 1, menuIds: [...] }`
2. 后端更新 `sys_role_menu` 表中 `roleId=1` 的记录
3. 所有使用 `roleId=1` 的用户权限都被更新
4. 包括"超级管理员"在内的所有 `roleId=1` 用户都受到影响
## 解决方案
### 方案1修改为基于用户的权限管理推荐但复杂
需要:
1. 创建 `sys_user_menu`
2. 修改后端API支持用户级别权限
3. 修改权限查询逻辑
4. 修改前端界面
### 方案2明确显示角色权限管理已实施
已实施的改进:
1. **界面标识**:添加"基于角色权限"标签
2. **角色ID显示**在用户列表中显示角色ID
3. **警告提示**:明确说明影响范围
4. **确认对话框**:保存前确认影响范围
5. **成功提示**:明确说明影响范围
## 修改内容
### 前端界面改进
1. **用户列表**
- 添加"基于角色权限"标签
- 显示角色ID列
2. **权限分配区域**
- 标题改为"角色权限分配"
- 显示当前角色ID
- 添加详细的警告提示
3. **保存确认**
- 添加确认对话框
- 明确说明影响范围
- 成功提示包含影响范围
### 警告信息内容
```
重要提示 - 基于角色的权限管理
• 当前系统使用基于角色的权限管理RBAC
• 修改权限会影响所有使用相同角色ID的用户
• 当前用户角色ID: 1
• 所有角色ID为 1 的用户都会受到影响
• 勾选操作权限后,该角色可以执行相应的按钮操作(新增、编辑、删除等)
```
## 建议
1. **短期解决方案**:使用当前的界面改进,让用户明确知道这是角色权限管理
2. **长期解决方案**:考虑实施基于用户的权限管理,但这需要较大的系统改造
3. **用户培训**:向用户说明权限管理机制,避免误解
## 技术细节
### 权限查询流程
```java
// 用户登录时获取权限
List<String> permissions = queryUserPermissions(user.getRoleId());
// 权限查询方法
private List<String> queryUserPermissions(Integer roleId) {
// 查询角色关联的菜单权限
List<SysMenu> menus = menuMapper.selectMenusByRoleId(roleId);
return menus.stream()
.filter(menu -> StringUtils.isNotEmpty(menu.getAuthority()))
.map(SysMenu::getAuthority)
.distinct()
.collect(Collectors.toList());
}
```
### 权限分配流程
```java
// 分配角色菜单权限
@PostMapping("/assignRoleMenus")
public AjaxResult assignRoleMenus(@RequestBody Map<String, Object> params) {
Integer roleId = (Integer) params.get("roleId");
List<Integer> menuIds = (List<Integer>) params.get("menuIds");
// 删除原有权限
sysRoleMenuMapper.delete(
new LambdaQueryWrapper<SysRoleMenu>()
.eq(SysRoleMenu::getRoleId, roleId)
);
// 添加新权限
for (Integer menuId : menuIds) {
SysRoleMenu roleMenu = new SysRoleMenu();
roleMenu.setRoleId(roleId);
roleMenu.setMenuId(menuId);
sysRoleMenuMapper.insert(roleMenu);
}
return AjaxResult.success("分配成功");
}
```
## 总结
这个问题的根本原因是系统使用基于角色的权限管理,而不是基于用户的权限管理。当修改权限时,影响的是整个角色,而不是单个用户。通过界面改进,现在用户可以清楚地了解权限管理机制和影响范围。