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

6.0 KiB
Raw Blame History

超级管理员用户专属权限修复报告

问题描述

用户"12.27新增姓名"ID: 3, roleId: 1设置了用户专属权限在权限管理界面中可以看到"装车订单"下的操作按钮(如"编辑"、"分配设备"、"删除"、"装车"等)都是未选中状态,表示这些按钮应该被隐藏。但是当用户登录后,这些操作按钮仍然显示。

问题原因

根本原因

用户"12.27新增姓名"的 roleId=1,而 RoleConstants.SUPER_ADMIN_ROLE_ID = 1,所以该用户被系统识别为超级管理员。

权限查询逻辑问题

LoginServiceImpl.javaqueryUserPermissions 方法中,存在以下逻辑:

// 原来的逻辑(有问题)
if (roleId.equals(RoleConstants.SUPER_ADMIN_ROLE_ID)) {
    log.info("=== 超级管理员用户 {} 使用所有权限", userId);
    return Collections.singletonList(RoleConstants.ALL_PERMISSION);
}

// 1. 先查询用户专属权限
List<SysMenu> userMenus = sysUserMenuMapper.selectMenusByUserId(userId);

问题如果用户是超级管理员角色roleId=1系统会直接返回所有权限 *:*:*完全跳过用户专属权限的检查

权限检查逻辑

在前端 hasPermi.js 中:

// 检查是否是超级管理员
const isSuperAdmin = userStore.permissions.includes('*:*:*') || userStore.roles.includes('admin');

// 只有非超级管理员且没有相应权限时才隐藏元素
if (!hasPermissions && !isSuperAdmin) {
    el.parentNode && el.parentNode.removeChild(el);
}

由于后端返回了 *:*:* 权限,前端识别为超级管理员,所以所有按钮都会显示。

修复方案

修改权限查询优先级

调整 queryUserPermissions 方法的逻辑顺序:

  1. 优先检查用户专属权限无论角色ID是什么
  2. 如果没有专属权限,再使用角色权限
  3. 超级管理员权限作为最后的fallback

修复后的逻辑

private List<String> queryUserPermissions(Integer userId, Integer roleId) {
    if (userId == null || roleId == null) {
        return Collections.emptyList();
    }
    
    // 1. 先查询用户专属权限(优先于角色权限)
    List<SysMenu> userMenus = sysUserMenuMapper.selectMenusByUserId(userId);
    if (userMenus != null && !userMenus.isEmpty()) {
        log.info("=== 用户 {} 使用专属权限,权限数量: {}", userId, userMenus.size());
        return userMenus.stream()
                .filter(menu -> StringUtils.isNotEmpty(menu.getAuthority()))
                .map(SysMenu::getAuthority)
                .distinct()
                .collect(Collectors.toList());
    }
    
    // 2. 如果没有专属权限,使用角色权限
    if (roleId.equals(RoleConstants.SUPER_ADMIN_ROLE_ID)) {
        log.info("=== 超级管理员用户 {} 使用所有权限(无专属权限)", userId);
        return Collections.singletonList(RoleConstants.ALL_PERMISSION);
    }
    
    // 3. 普通角色权限
    log.info("=== 用户 {} 使用角色权限roleId: {}", userId, roleId);
    List<SysMenu> roleMenus = menuMapper.selectMenusByRoleId(roleId);
    return roleMenus.stream()
            .filter(menu -> StringUtils.isNotEmpty(menu.getAuthority()))
            .map(SysMenu::getAuthority)
            .distinct()
            .collect(Collectors.toList());
}

修复内容

文件:tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/service/impl/LoginServiceImpl.java

修改位置第166-196行的 queryUserPermissions 方法

修改内容

  • 将用户专属权限检查提前到角色权限检查之前
  • 确保即使超级管理员角色ID的用户也能使用专属权限
  • 只有在没有专属权限时才使用超级管理员权限

修复效果

修复前

  • 超级管理员角色ID的用户无法使用专属权限
  • 用户"12.27新增姓名"设置了专属权限但按钮仍然显示
  • 权限优先级:超级管理员权限 > 用户专属权限

修复后

  • 用户专属权限优先于所有角色权限
  • 超级管理员角色ID的用户也能使用专属权限
  • 权限优先级:用户专属权限 > 角色权限 > 超级管理员权限

测试验证

测试步骤

  1. 重新编译后端mvn clean compile
  2. 重启后端服务mvn spring-boot:run
  3. 清除浏览器缓存
  4. 使用"12.27新增姓名"账号登录
  5. 检查装车订单页面的操作按钮

预期结果

  • 用户"12.27新增姓名"登录后,装车订单页面的操作按钮应该根据专属权限设置被隐藏
  • 控制台日志应该显示"用户 3 使用专属权限"
  • 权限检查应该显示 isSuperAdmin: false

技术说明

权限优先级设计

1. 用户专属权限(最高优先级)
   ↓
2. 角色权限(普通用户)
   ↓
3. 超级管理员权限fallback

向后兼容性

  • 没有设置专属权限的超级管理员用户仍然使用所有权限
  • 没有设置专属权限的普通用户仍然使用角色权限
  • 现有功能不受影响

日志输出

修复后的日志输出示例:

=== 用户 3 使用专属权限,权限数量: 15

而不是:

=== 超级管理员用户 3 使用所有权限

相关文件

  • tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/service/impl/LoginServiceImpl.java - 权限查询逻辑
  • pc-cattle-transportation/src/directive/permission/hasPermi.js - 前端权限检查
  • pc-cattle-transportation/src/views/permission/operationPermission.vue - 权限管理界面

总结

通过调整权限查询的优先级成功解决了超级管理员角色ID用户无法使用专属权限的问题。修复后的系统能够

  1. 正确识别用户专属权限即使角色ID是超级管理员
  2. 按预期隐藏操作按钮:根据专属权限设置
  3. 保持向后兼容性:不影响现有功能
  4. 提供清晰的日志:便于调试和监控

修复状态 已完成 测试状态 待验证 部署状态 已部署