# 403权限问题修复说明 ## 问题原因 用户登录后跳转到403无权限页面,主要原因有: 1. **缺少 home 路由权限**:所有角色的 menus 字段都没有包含 `home`,导致登录后无法访问首页 2. **路由名称格式不一致**: - R_USER 角色配置的是 `my_device`(下划线) - 但实际路由名称是 `my-device`(连字符) - 导致权限匹配失败 3. **前端路由守卫检查 roles**: - 后端返回的路由 meta 中包含 roles 字段 - 前端路由守卫会检查用户是否有对应的 roles - 但在动态路由模式下,后端已经根据用户角色过滤了路由 - 前端不应该再次检查 roles,否则会导致403错误 ## 路由命名规则 - **父路由**:使用连字符(kebab-case),如 `user-manage`、`my-device`、`my-application` - **子路由**:使用下划线,如 `user-manage_list`、`my-device_status`、`my-application_apply` ## 修复步骤 ### 1. 运行数据库修复脚本 ```bash fix_403_complete.bat ``` 或者手动执行SQL: ```bash mysql -u root -proot < fix_403_complete.sql ``` 这个脚本会: - 为所有角色添加 `home` 路由权限 - 修正路由名称格式(父路由用连字符,子路由用下划线) - 确保角色的 menus 字段与数据库中的路由名称一致 ### 2. 重启后端服务 修复数据库后,**必须重启** Spring Boot后端服务: ```bash cd backend mvn spring-boot:run ``` 或者在IDE中重启应用。 **重要**:后端代码已经修改,会自动移除路由 meta 中的 roles 字段,避免前端重复检查权限。 ### 3. 清除浏览器缓存并重新登录 - 按 Ctrl+Shift+Delete 清除浏览器缓存 - 或者使用无痕模式/隐私模式 - 退出登录 - 重新登录测试 ## 修复后的角色权限配置 ### R_SUPER(超级管理员) 拥有所有菜单权限: - home(首页) - device(设备管理)及所有子菜单 - screen(屏幕监控)及所有子菜单 - user-manage(用户管理)及所有子菜单 - application(使用申请)及所有子菜单 - system(系统设置)及所有子菜单 - my-device(我的设备)及所有子菜单 - my-application(设备申请)及所有子菜单 ### R_ADMIN(管理员) 除系统设置外的所有管理功能: - home(首页) - device(设备管理)及所有子菜单 - screen(屏幕监控)及所有子菜单 - user-manage(用户管理):列表和角色管理(不包括权限管理) - application(使用申请)及所有子菜单 ### R_USER(普通用户) 只能访问自己的设备和申请: - home(首页) - my-device(我的设备)及所有子菜单 - my-application(设备申请)及所有子菜单 ### R_STU(学生) 只能访问首页: - home(首页) ## 验证修复 ### 1. 检查数据库 ```sql -- 查看角色配置 SELECT role_code, role_name, menus FROM sys_role; -- 查看路由配置 SELECT name, path, component FROM sys_route WHERE status = 1 ORDER BY order_num; ``` ### 2. 测试登录 使用不同角色的账号登录测试: - **admin/admin123**(R_SUPER + R_ADMIN):应该能看到所有菜单 - **user/user123**(R_USER):应该只能看到首页、我的设备、设备申请 ### 3. 查看后端日志 登录后查看后端控制台输出,应该能看到类似以下的调试信息: ``` === 用户路由权限调试 === 用户ID: 1 用户角色: R_SUPER,R_ADMIN 查询到的角色数量: 2 角色: R_SUPER - 超级管理员 配置的菜单: home,device,device_list,... 允许访问的菜单: [home, device, device_list, ...] ``` ## 常见问题 ### Q1: 修复后还是403? A: 请确保: 1. 已重启后端服务 2. 已清除浏览器缓存 3. 已重新登录 4. 检查后端日志确认菜单配置已更新 ### Q2: 某些菜单看不到? A: 检查: 1. 该菜单是否在角色的 menus 字段中 2. 路由名称是否正确(父路由用连字符,子路由用下划线) 3. 路由表中是否存在该路由且 status=1 ### Q3: 如何添加新菜单权限? A: 1. 在 sys_route 表中添加新路由 2. 在 sys_role 表的 menus 字段中添加对应的路由名称 3. 重启后端服务 ## 技术细节 ### 后端权限过滤逻辑 `RouteService.getUserRoutes()` 方法: 1. 根据用户ID查询用户信息 2. 获取用户的角色列表(roles字段) 3. 查询这些角色的菜单配置(menus字段) 4. 合并所有角色的菜单权限 5. 自动添加父菜单(如果配置了子菜单) 6. 从路由表中过滤出用户有权限的路由 7. **移除路由 meta 中的 roles 字段**(避免前端重复检查) 8. 构建路由树并返回 ### 前端路由处理 前端使用动态路由模式(`VITE_AUTH_ROUTE_MODE=dynamic`): 1. 登录成功后调用 `/route/getUserRoutes` 获取用户路由 2. 前端根据返回的路由动态生成菜单 3. **前端路由守卫检查逻辑**: - 检查路由的 `meta.roles` 字段 - 如果路由有 roles 且用户没有对应角色,跳转403 - **在动态路由模式下,后端已过滤路由,meta 中不应包含 roles** 4. 如果访问未授权的路由,会跳转到403页面 ### 修复的关键点 **后端修改**(`RouteService.java`): ```java // 移除 roles 字段,因为后端已经根据角色过滤了路由 // 前端不需要再次检查 roles meta.remove("roles"); ``` 这样前端路由守卫就不会检查 roles,避免403错误。 ## 相关文件 - `backend/src/main/java/com/soybean/admin/service/RouteService.java` - 路由权限过滤逻辑 - `backend/src/main/java/com/soybean/admin/entity/Role.java` - 角色实体 - `backend/src/main/resources/sql/init.sql` - 数据库初始化脚本 - `fix_403_complete.sql` - 权限修复脚本