Token机制调整完成报告.md 12 KB

本次调整说明

  • 1、LQAdminFront 前端调用接口返回401 无效的访问令牌,直接调整到登录页面
  • 2、LQAdminPlatform 后台管理调整
    • 2.1、验证token是否按预期处理,用户每次请求后台接口时,token的时长将重置,只有用户在token设置时间范围内都没有请求 才作为token超时(需要重新登录)
    • 2.2、用户每次访问后台接口时,日志打印token配置时长、当前token的创建时间、使用时长、剩余时长、刷新token时长信息,用于验证token是否按预期处理

token 再最大时间范围内自动重置处理问题

  • 测试情况如下:
    • 首次登录后 18:00:00
      • token配置时长:5 分钟
      • Token创建时间: 18:00:00
      • Token过期时间: 18:05:00
    • 时间到 18:04:00 访问一次后台请求,可以正常访问
    • 时间到 18:05:10 访问二次后台请求时 token已经失效,需要重新登录
    • 正常情况下本次情况可以正常访问,因为18:04的时候访问过一次,这时token时间已经重置,并且token需要等到 18:10:10分才会过期
    • 并且为什么每次后台请求的时候 没有打印token验证信息呢?按理说每次后台API请求的时候都会验证token,都会打印token验证信息的

用户列表接口和角色列表接口 都按要求增加get_current_user_with_refresh ,token还是同样的问题,未得到解决

@router.get("/admin/users") async def get_users(

request: Request,
current_user: dict = Depends(get_current_user_with_refresh),
page: int = 1,
page_size: int = 20,
keyword: Optional[str] = None

):

@router.get("/admin/roles") async def api_get_all_roles(

request: Request,
current_user: dict = Depends(get_current_user_with_refresh),
page: int = 1,
page_size: int = 20,
keyword: Optional[str] = None,
#credentials: HTTPAuthorizationCredentials = Depends(security)

):


🔍 当前状态(2026-02-08)

✅ 已完成的工作

  1. 前端401处理 - 完成

    • 同时处理HTTP 401和业务错误码401
    • 多重跳转保障机制
    • 自动清除认证信息
  2. 后端Token验证和刷新逻辑 - 完成

    • verify_and_refresh_token() 函数实现滑动过期
    • 详细的token日志输出
    • 刷新阈值设置为50%
  3. 认证依赖函数 - 完成

    • get_current_user_with_refresh 已创建
    • 包含详细的调试日志(>>> [依赖函数] 开头)
    • 会将新token存储到 request.state.new_token
  4. 响应处理中间件 - 完成

    • 检查 request.state.new_token
    • 添加 X-New-Token 到响应头
    • 包含详细的调试日志(>>> [响应中间件] 开头)
  5. 中间件注册 - 完成

    • TokenRefreshMiddleware 已注册
    • 响应处理中间件已注册
    • 启动时会打印注册成功日志
  6. 视图函数更新 - 部分完成

    • ✅ 用户列表接口已使用新依赖
    • ✅ 角色列表接口已使用新依赖
    • ⚠️ 其他接口仍使用旧的 verify_token

❌ 问题现象

用户反馈:即使用户列表和角色列表接口已使用新依赖,token仍然没有刷新。

🎯 下一步操作

关键:必须重启后台服务器!

代码修改后,如果没有重启服务器,修改不会生效。

步骤1: 运行诊断脚本

cd LQAdminPlatform
python 诊断Token刷新问题.py

这个脚本会检查:

  • 所有关键文件是否存在
  • 配置是否正确
  • 依赖函数是否正确实现
  • 中间件是否正确注册
  • 视图函数是否使用新依赖

步骤2: 重启后台服务器

cd LQAdminPlatform
# 按 Ctrl+C 停止当前服务器
python src/main.py

检查启动日志,必须看到:

✅ Token刷新中间件已注册
✅ Token响应处理中间件已注册

步骤3: 测试Token刷新

详细步骤请查看:快速测试Token刷新.md

简要步骤:

  1. 登录系统(记录时间,如 18:00:00)
  2. 等待3分钟(超过2.5分钟阈值)
  3. 访问用户列表或角色列表
  4. 查看后台日志

预期日志

>>> [响应中间件] 处理请求: /api/v1/system/admin/users
>>> [依赖函数] get_current_user_with_refresh 被调用
Token验证信息 - 用户: admin
  Token配置时长: 5 分钟
  Token已使用时长: 3.00 分钟
  Token刷新: 已使用时长超过阈值,生成新token
>>> [依赖函数] Token已刷新,新token已存储到request.state
>>> [响应中间件] 发现新token,添加到响应头

步骤4: 检查响应头

在浏览器开发者工具 -> Network -> 选择请求 -> Headers -> Response Headers

应该看到:

X-New-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
X-Token-Refreshed: true

步骤5: 检查浏览器控制台

应该看到:

Token已自动刷新

📚 相关文档

  1. 快速测试Token刷新.md - 5分钟快速测试指南
  2. 调试Token刷新问题.md - 详细的调试步骤和检查点
  3. 诊断Token刷新问题.py - 自动诊断脚本
  4. 如何使用新的认证依赖.md - 如何在其他接口中使用新依赖

🐛 可能的问题

  1. 服务器没有重启 - 最常见的问题
  2. 日志级别不对 - 确保 LOG_LEVEL=INFO
  3. 等待时间不够 - 必须超过2.5分钟
  4. 访问了错误的接口 - 必须访问使用新依赖的接口
  5. 前端没有重启 - 前端代码修改后也需要重启

💡 提示

  • 所有带 >>> 前缀的日志都是为了调试添加的,方便快速定位问题
  • 如果看不到这些日志,说明对应的代码没有执行
  • 日志会按顺序输出,可以看出执行流程

Token机制调整实现说明

调整内容

1. 前端调整(LQAdminFront)✅

文件: LQAdminFront/src/api/request.ts

改动说明:

  • 当接口返回 401 无效的访问令牌时,前端不再尝试刷新token
  • 直接清除本地认证信息并跳转到登录页面
  • 提示用户"无效的访问令牌,请重新登录"

测试方法:

  1. 正常登录系统
  2. 手动修改浏览器 localStorage 中的 token 为无效值
  3. 刷新页面或访问任意需要认证的接口
  4. 验证是否自动跳转到登录页面并显示提示信息

2. 后台调整(LQAdminPlatform)✅

2.1 Token滑动过期机制验证

文件: LQAdminPlatform/src/app/services/jwt_token.py

改动说明:

  • Token采用滑动过期机制:用户每次请求后台接口时,如果token已使用时长超过总时长的一半,则自动刷新token
  • 只有用户在token设置时间范围内都没有请求,才会导致token超时(需要重新登录)

配置参数:

  • ADMIN_TOKEN_EXPIRE_MINUTES: Token总有效期(分钟),当前配置为 60 分钟
  • 刷新阈值:Token使用时长超过总时长的 50% 时自动刷新

测试方法:

  1. 登录系统获取token
  2. 在30分钟内持续访问接口,观察token是否自动刷新
  3. 停止访问超过60分钟,再次访问应返回401需要重新登录
  4. 查看后台日志验证token信息是否正确打印

2.2 Token详细日志记录

文件:

  • LQAdminPlatform/src/app/services/jwt_token.py
  • LQAdminPlatform/src/app/middleware/token_refresh_middleware.py

改动说明: 用户每次访问后台接口时,日志会打印以下信息:

Token验证信息 - 用户: admin
  Token配置时长: 60 分钟
  Token创建时间: 2026-02-08 10:00:00 UTC
  Token过期时间: 2026-02-08 11:00:00 UTC
  Token已使用时长: 15.50 分钟 (930 秒)
  Token剩余时长: 44.50 分钟 (2670 秒)
  Token刷新: 未达到刷新阈值 (30.00 分钟),继续使用当前token

当token被刷新时:

Token刷新: 已使用时长超过阈值 (30.00 分钟),生成新token
Token已刷新,用户: admin, 路径: /api/system/profile

测试方法:

  1. 启动后台服务
  2. 登录系统
  3. 访问任意需要认证的接口
  4. 查看后台日志文件(logs/lq-admin-app.log 或控制台输出)
  5. 验证是否打印了完整的token信息

验证要点

Token滑动过期机制验证

  1. 正常使用场景(应该不会超时):

    • 用户持续操作,每隔10-20分钟访问一次接口
    • Token应该自动刷新,用户无需重新登录
    • 日志应显示token刷新记录
  2. 长时间不操作场景(应该超时):

    • 用户登录后60分钟内不进行任何操作
    • 60分钟后访问接口应返回401
    • 前端自动跳转到登录页
  3. 边界测试:

    • 在第29分钟访问:不应刷新
    • 在第31分钟访问:应该刷新
    • 在第59分钟访问:应该刷新且继续有效
    • 在第61分钟访问:应该返回401

日志验证

检查日志中是否包含:

  • ✅ Token配置时长
  • ✅ Token创建时间
  • ✅ Token过期时间
  • ✅ Token已使用时长
  • ✅ Token剩余时长
  • ✅ Token刷新决策信息(是否刷新及原因)

配置说明

Token时长配置位于 LQAdminPlatform/src/app/config/config.ini:

[admin_app]
# 后台管理Token配置
ADMIN_TOKEN_EXPIRE_MINUTES=60  # Token总有效期(分钟)
ADMIN_REFRESH_TOKEN_EXPIRE_HOURS=24  # Refresh Token有效期(小时)

可根据实际需求调整这些参数。

注意事项

  1. Token刷新是自动的,前端会在响应头中接收新token(X-New-Token)
  2. 前端需要处理响应头中的新token并更新本地存储(如果有相关逻辑)
  3. 所有时间计算使用UTC时区,避免时区问题
  4. 日志级别需要设置为INFO或更低才能看到详细的token信息

问题根源和修复 ✅

问题发现

从错误堆栈 request.ts:65:27 可以看出,错误发生在成功响应拦截器中,而不是401错误处理器中。

原因: 后台返回的是 HTTP 200 + 业务错误码401,而不是 HTTP 401

HTTP/1.1 200 OK
{
  "code": 401,
  "message": "无效的访问令牌"
}

修复方案

在成功响应拦截器中添加了对业务错误码401的检查:

  • 检测到 code === 401 时立即跳转
  • 清除所有存储
  • 显示错误提示
  • 阻止后续执行

现在代码同时处理两种401情况:

  1. HTTP状态码401(中间件返回)
  2. HTTP 200 + 业务错误码401(业务逻辑返回)

修改文件清单

  1. LQAdminFront/src/api/request.ts - 前端401处理逻辑 + Token自动更新(已增强调试日志和多重跳转保障)
  2. LQAdminPlatform/src/app/services/jwt_token.py - Token验证和刷新逻辑,添加详细日志
  3. LQAdminPlatform/src/app/middleware/token_refresh_middleware.py - 中间件日志增强

前端401跳转问题修复

问题

前端调用接口返回401时没有自动跳转到登录页面。

解决方案

LQAdminFront/src/api/request.ts 中实施了以下增强:

  1. 详细的调试日志: 每个步骤都输出日志,方便排查问题
  2. 多重跳转保障:
    • 方法1: router.push('/login')
    • 方法2: router.replace('/login') (如果push失败)
    • 方法3: window.location.href = '/login' (最后的保障)
  3. 强制清除认证信息: 直接操作localStorage确保token被清除

测试步骤

重要!修改后必须重启前端开发服务器:

# 停止当前服务器(Ctrl+C)
cd LQAdminFront
npm run dev

清除浏览器缓存:

  • 按F12打开开发者工具
  • 右键点击刷新按钮
  • 选择"清空缓存并硬性重新加载"

测试401跳转:

  1. 正常登录系统
  2. 打开开发者工具(F12)-> Application -> Local Storage
  3. 修改 sso_access_token 的值为 invalid_token_test
  4. 刷新页面或点击任意菜单
  5. 观察控制台日志和页面跳转

预期结果:

  • ✅ 控制台显示 === 401错误处理开始 === 等日志
  • ✅ 页面自动跳转到登录页
  • ✅ 显示提示:"无效的访问令牌,请重新登录"
  • ✅ localStorage中的token被清除

排查指南

详细的排查步骤请查看:LQAdminFront/401跳转问题排查指南.md

前端Token自动更新机制

前端响应拦截器会自动检查响应头中的 X-New-Token,如果存在则自动更新本地存储的token:

// 检查响应头中是否有新的token(滑动过期机制)
const newToken = response.headers['x-new-token']
if (newToken) {
  // 更新本地存储的token,保留原有的refresh token
  const refreshToken = getRefreshToken()
  saveToken(newToken, refreshToken || undefined)
  console.log('Token已自动刷新')
}

这样用户在正常使用过程中,token会自动刷新,无需手动处理。