在使用若依(RuoYi)小程序时,用户登录后生成的Token在一定时间后会自动失效,导致后续接口请求返回“401 未授权”错误。常见问题是:当Token过期后,前端未及时捕获异常并重新登录,造成页面无法正常获取数据或功能中断。如何在Token失效时实现无感刷新或自动跳转至登录页,成为提升用户体验的关键。尤其在长时间停留或后台运行后进入小程序时,该问题尤为突出。需结合本地缓存、拦截器和Token刷新机制进行优化处理。
1条回答 默认 最新
泰坦V 2025-12-15 08:43关注1. 问题背景与常见现象
在使用若依(RuoYi)小程序时,用户登录后系统会生成一个JWT Token用于身份认证。该Token通常设置有有效期(如2小时),超时后将自动失效。当用户在长时间未操作或小程序在后台运行一段时间后再次唤醒,此时发起的接口请求因携带已过期的Token,服务器返回
401 Unauthorized错误。常见的表现包括:页面数据无法加载、按钮点击无响应、表单提交失败等。由于前端未对401状态码进行统一拦截处理,导致用户体验中断,需手动退出重新登录。
2. 技术分析过程
- Token机制原理: RuoYi采用基于JWT的无状态认证方案,Token由服务端签发并包含过期时间(exp字段)。
- 前端存储方式: 小程序中Token通常存于本地缓存(如
uni.setStorageSync('token'))。 - 请求拦截缺失: 多数项目未配置全局响应拦截器,未能捕获401状态码。
- 刷新机制空白: 缺少利用Refresh Token进行无感续期的设计。
- 生命周期影响: 小程序的
onHide和onShow未结合Token有效性检查。
3. 解决方案设计维度
维度 描述 技术实现点 拦截机制 统一处理HTTP响应 使用 uni.addInterceptor或封装request模块Token刷新 通过Refresh Token获取新Access Token 调用 /login/refresh接口本地缓存管理 安全存储并及时更新Token uni.setStorageSync配合内存变量无感刷新逻辑 避免重复刷新、防止并发请求多次登录 Promise锁机制 + 队列等待 降级策略 刷新失败时跳转至登录页 清除缓存 + 页面重定向 4. 核心代码实现
// utils/request.js let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach(prom => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; uni.addInterceptor('request', { invoke(args) { const token = uni.getStorageSync('token'); if (token) { args.header['Authorization'] = 'Bearer ' + token; } } }); uni.addInterceptor('request', { fail(err) { console.error('Request failed:', err); }, success(res) { if (res.statusCode === 401) { const config = res.config || {}; if (!config.isRetry) { if (!isRefreshing) { isRefreshing = true; refreshToken().then(newToken => { uni.setStorageSync('token', newToken); processQueue(null, newToken); // 重试原请求 config.isRetry = true; uni.request(config); }).catch(() => { processQueue(new Error('Token refresh failed'), null); clearAuthData(); uni.reLaunch({ url: '/pages/login/index' }); }).finally(() => { isRefreshing = false; }); } else { // 等待刷新完成 return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }).then(token => { config.header.Authorization = 'Bearer ' + token; uni.request(config); }).catch(err => { console.error(err); }); } } } } });5. 流程图:Token无感刷新机制
graph TD A[发起API请求] --> B{响应状态码} B -- 200 OK --> C[正常返回数据] B -- 401 Unauthorized --> D{是否正在刷新Token?} D -- 否 --> E[调用refreshToken接口] E --> F{刷新成功?} F -- 是 --> G[更新本地Token] G --> H[重试原请求] F -- 否 --> I[清除认证信息] I --> J[跳转至登录页] D -- 是 --> K[加入等待队列] K --> L[等待新Token分发] L --> M[使用新Token重试]6. 拓展优化建议
- Token预刷新机制: 在Token剩余有效期小于5分钟时主动刷新,避免临界点失效。
- 内存+持久化双存储: 使用变量缓存Token提升读取效率,同时持久化防止冷启动丢失。
- 多端登录冲突处理: 服务端维护Token黑名单列表,防止旧Token被恶意复用。
- 日志埋点监控: 记录401触发频率、刷新成功率,辅助性能调优。
- 加密存储增强: 对敏感Token进行混淆或AES加密后再存入本地。
- WebSocket心跳同步: 长连接场景下可监听服务端推送的登出指令。
- 版本兼容性控制: 不同RuoYi版本(如V3/V4)的刷新接口路径可能存在差异。
- 自动化测试覆盖: 使用UniApp自动化测试工具模拟Token过期场景。
- 灰度发布策略: 新增刷新逻辑时先小范围上线验证稳定性。
- 用户行为提示: 刷新失败后可弹窗提示“登录状态已过期,请重新登录”。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报