guoyu/_已清理文件备份_周六 22512/md/代码检查报告.md
2025-12-06 20:11:36 +08:00

5.9 KiB
Raw Blame History

登录日志 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

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<String> 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检查数据库权限配置

-- 检查用户是否有 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如果权限缺失执行修复

-- 参考 fix_logininfor_permission.sql 文件

步骤 3清除 Redis 缓存

# 在 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. 重新登录测试