#### 本次调整说明 - 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: 运行诊断脚本 ```bash cd LQAdminPlatform python 诊断Token刷新问题.py ``` 这个脚本会检查: - 所有关键文件是否存在 - 配置是否正确 - 依赖函数是否正确实现 - 中间件是否正确注册 - 视图函数是否使用新依赖 #### 步骤2: 重启后台服务器 ```bash 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`: ```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被清除 ### 测试步骤 **重要!修改后必须重启前端开发服务器:** ```bash # 停止当前服务器(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: ```typescript // 检查响应头中是否有新的token(滑动过期机制) const newToken = response.headers['x-new-token'] if (newToken) { // 更新本地存储的token,保留原有的refresh token const refreshToken = getRefreshToken() saveToken(newToken, refreshToken || undefined) console.log('Token已自动刷新') } ``` 这样用户在正常使用过程中,token会自动刷新,无需手动处理。