Files
cattleTransportation/pc-cattle-transportation/PERMISSION_MANAGEMENT_EXPLANATION.md
2025-10-23 17:28:06 +08:00

4.7 KiB
Raw Blame 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. 权限获取流程

    // 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. 用户培训:向用户说明权限管理机制,避免误解

技术细节

权限查询流程

// 用户登录时获取权限
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());
}

权限分配流程

// 分配角色菜单权限
@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("分配成功");
}

总结

这个问题的根本原因是系统使用基于角色的权限管理,而不是基于用户的权限管理。当修改权限时,影响的是整个角色,而不是单个用户。通过界面改进,现在用户可以清楚地了解权限管理机制和影响范围。