普通网友 2025-12-15 07:20 采纳率: 98.9%
浏览 1
已采纳

若依小程序登录Token失效如何处理?

在使用若依(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进行无感续期的设计。
    • 生命周期影响: 小程序的onHideonShow未结合Token有效性检查。

    3. 解决方案设计维度

    维度描述技术实现点
    拦截机制统一处理HTTP响应使用uni.addInterceptor或封装request模块
    Token刷新通过Refresh Token获取新Access Token调用/login/refresh接口
    本地缓存管理安全存储并及时更新Tokenuni.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. 拓展优化建议

    1. Token预刷新机制: 在Token剩余有效期小于5分钟时主动刷新,避免临界点失效。
    2. 内存+持久化双存储: 使用变量缓存Token提升读取效率,同时持久化防止冷启动丢失。
    3. 多端登录冲突处理: 服务端维护Token黑名单列表,防止旧Token被恶意复用。
    4. 日志埋点监控: 记录401触发频率、刷新成功率,辅助性能调优。
    5. 加密存储增强: 对敏感Token进行混淆或AES加密后再存入本地。
    6. WebSocket心跳同步: 长连接场景下可监听服务端推送的登出指令。
    7. 版本兼容性控制: 不同RuoYi版本(如V3/V4)的刷新接口路径可能存在差异。
    8. 自动化测试覆盖: 使用UniApp自动化测试工具模拟Token过期场景。
    9. 灰度发布策略: 新增刷新逻辑时先小范围上线验证稳定性。
    10. 用户行为提示: 刷新失败后可弹窗提示“登录状态已过期,请重新登录”。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 12月16日
  • 创建了问题 12月15日