# 权限管理机制说明 ## 问题描述 用户反映:修改"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 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 permissions = queryUserPermissions(user.getRoleId()); // 权限查询方法 private List queryUserPermissions(Integer roleId) { // 查询角色关联的菜单权限 List 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 params) { Integer roleId = (Integer) params.get("roleId"); List menuIds = (List) params.get("menuIds"); // 删除原有权限 sysRoleMenuMapper.delete( new LambdaQueryWrapper() .eq(SysRoleMenu::getRoleId, roleId) ); // 添加新权限 for (Integer menuId : menuIds) { SysRoleMenu roleMenu = new SysRoleMenu(); roleMenu.setRoleId(roleId); roleMenu.setMenuId(menuId); sysRoleMenuMapper.insert(roleMenu); } return AjaxResult.success("分配成功"); } ``` ## 总结 这个问题的根本原因是系统使用基于角色的权限管理,而不是基于用户的权限管理。当修改权限时,影响的是整个角色,而不是单个用户。通过界面改进,现在用户可以清楚地了解权限管理机制和影响范围。