5.9 KiB
5.9 KiB
登录日志 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.javary-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 中仍是旧权限
- 解决方法:
- 清除 Redis 缓存:
KEYS login_tokens:*然后删除 - 或者重启 Redis
- 重新登录系统
- 清除 Redis 缓存:
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:重新登录并测试
- 清除浏览器 Cookie
- 重新登录系统
- 测试登录日志页面
🎯 结论
代码检查结果:所有代码正常,无差异。
问题定位: 问题不在代码层面,而是在数据层面:
- 数据库权限配置可能不完整
- Redis 缓存可能过期
建议操作:
- 执行
check_permissions.sql检查权限配置 - 如果权限缺失,执行
fix_logininfor_permission.sql修复 - 清除 Redis 缓存
- 重新登录测试