# 权限管理机制说明

## 问题描述

用户反映：修改"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("分配成功");
}
```

## 总结

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