# 登录日志 401 错误代码检查报告 ## 检查时间 2025-01-30 ## 检查范围 - 前端 API 调用 - 前端页面组件 - 后端控制器 - 权限检查逻辑 - Token 处理 ## 检查结果 ### ✅ 前端代码检查 #### 1. API 调用对比 **文件:`study-ui/src/api/monitor/logininfor.js` vs `operlog.js`** | 项目 | logininfor | operlog | 状态 | |------|-----------|---------|------| | URL 路径 | `/monitor/logininfor/list` | `/monitor/operlog/list` | ✅ 一致 | | 请求方法 | `get` | `get` | ✅ 一致 | | 参数处理 | `params: query` | `params: query` | ✅ 一致 | | 导入方式 | `import request from '@/utils/request'` | `import request from '@/utils/request'` | ✅ 一致 | **结论:** 前端 API 调用代码完全一致,无差异。 #### 2. 页面组件对比 **文件:`study-ui/src/views/monitor/logininfor/index.vue` vs `operlog/index.vue`** | 项目 | logininfor | operlog | 状态 | |------|-----------|---------|------| | 生命周期 | `created()` 中调用 `getList()` | `created()` 中调用 `getList()` | ✅ 一致 | | 错误处理 | 无 `.catch()` | 无 `.catch()` | ✅ 一致 | | 列表查询方法 | `list(this.addDateRange(...))` | `list(this.addDateRange(...))` | ✅ 一致 | **结论:** 页面组件实现完全一致,无差异。 #### 3. 请求拦截器检查 **文件:`study-ui/src/utils/request.js`** - ✅ Token 添加逻辑正常:`config.headers['Authorization'] = 'Bearer ' + getToken()` - ✅ GET 请求参数处理正常 - ✅ 响应拦截器 401 处理正常 **结论:** 请求拦截器配置正常。 ### ✅ 后端代码检查 #### 1. 控制器对比 **文件:** - `ry-study-admin/.../SysLogininforController.java` - `ry-study-admin/.../SysOperlogController.java` | 项目 | SysLogininforController | SysOperlogController | 状态 | |------|------------------------|---------------------|------| | 注解 | `@RestController` | `@RestController` | ✅ 一致 | | 路径映射 | `@RequestMapping("/monitor/logininfor")` | `@RequestMapping("/monitor/operlog")` | ✅ 一致 | | 权限注解 | `@PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")` | `@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")` | ✅ 一致 | | 方法实现 | `startPage()` + `selectLogininforList()` | `startPage()` + `selectOperLogList()` | ✅ 一致 | | 返回类型 | `TableDataInfo` | `TableDataInfo` | ✅ 一致 | **结论:** 控制器代码完全一致,无差异。 #### 2. 权限检查逻辑 **文件:`ry-study-framework/.../PermissionService.java`** ```java public boolean hasPermi(String permission) { if (StringUtils.isEmpty(permission)) { return false; } LoginUser loginUser = SecurityUtils.getLoginUser(); if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) { return false; } PermissionContextHolder.setContext(permission); return hasPermissions(loginUser.getPermissions(), permission); } private boolean hasPermissions(Set permissions, String permission) { return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); } ``` **检查点:** - ✅ 权限检查逻辑正常 - ✅ 支持通配符权限 `*:*:*` - ✅ 权限字符串会进行 trim 处理 **结论:** 权限检查逻辑正常,无问题。 #### 3. Token 处理 **文件:`ry-study-framework/.../JwtAuthenticationTokenFilter.java`** - ✅ Token 提取逻辑正常 - ✅ 用户信息从 Redis 获取 - ✅ 权限信息从 `LoginUser.getPermissions()` 获取 **结论:** Token 处理逻辑正常。 ## 🔍 问题分析 ### 代码层面 **所有代码检查均正常,无差异。** ### 可能的问题原因 #### 1. 数据库权限配置问题 ⚠️(最可能) - **现象:** 菜单配置显示"正常",但用户实际没有该权限 - **原因:** - `sys_role_menu` 表中缺少角色与 `monitor:logininfor:list` 菜单的关联 - 或者用户角色关联不正确 - **验证方法:** 执行 `check_permissions.sql` 中的查询 #### 2. Redis 缓存问题 ⚠️ - **现象:** 数据库权限已更新,但 Redis 中仍是旧数据 - **原因:** - 用户登录后,权限信息缓存在 Redis 中 - 如果数据库权限更新,但用户未重新登录,Redis 中仍是旧权限 - **解决方法:** 1. 清除 Redis 缓存:`KEYS login_tokens:*` 然后删除 2. 或者重启 Redis 3. 重新登录系统 #### 3. 权限字符串差异 ⚠️ - **现象:** 权限字符串可能有细微差异(空格、大小写等) - **验证方法:** 检查数据库中 `sys_menu.perms` 字段的值 ## 📋 建议的排查步骤 ### 步骤 1:检查数据库权限配置 ```sql -- 检查用户是否有 monitor:logininfor:list 权限 SELECT u.user_name, r.role_name, m.perms FROM sys_user u LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id LEFT JOIN sys_role r ON ur.role_id = r.role_id LEFT JOIN sys_role_menu rm ON r.role_id = rm.role_id LEFT JOIN sys_menu m ON rm.menu_id = m.menu_id WHERE u.user_name = 'admin' -- 替换为你的用户名 AND m.perms IN ('monitor:logininfor:list', 'monitor:operlog:list') ORDER BY m.perms; ``` ### 步骤 2:如果权限缺失,执行修复 ```sql -- 参考 fix_logininfor_permission.sql 文件 ``` ### 步骤 3:清除 Redis 缓存 ```bash # 在 Redis 中执行 KEYS login_tokens:* # 删除所有匹配的 key # 或者 FLUSHDB # 仅开发环境 ``` ### 步骤 4:重新登录并测试 1. 清除浏览器 Cookie 2. 重新登录系统 3. 测试登录日志页面 ## 🎯 结论 **代码检查结果:所有代码正常,无差异。** **问题定位:** 问题不在代码层面,而是在数据层面: 1. 数据库权限配置可能不完整 2. Redis 缓存可能过期 **建议操作:** 1. 执行 `check_permissions.sql` 检查权限配置 2. 如果权限缺失,执行 `fix_logininfor_permission.sql` 修复 3. 清除 Redis 缓存 4. 重新登录测试