Android并发场景下的Token失效问题:原理分析与实战解决方案

1次阅读
没有评论

共计 1193 个字符,预计需要花费 3 分钟才能阅读完成。

image.webp

问题背景:当 Token 遇上并发

开发中经常遇到这种情况:用户快速切换界面时,突然弹出多个登录失效提示。查看日志会发现大量 401 错误集中爆发——这就是典型的并发 Token 失效问题。当多个请求同时检测到 Token 过期时,可能触发多次刷新请求,导致服务器拒绝服务或新 Token 被覆盖。

Android 并发场景下的 Token 失效问题:原理分析与实战解决方案

原理拆解:Token 的生命周期

  1. 双 Token 机制:Access Token(短期有效)和 Refresh Token(长期有效)配合工作。前者用于业务请求,后者专用于 Token 刷新
  2. 多线程竞争场景:当三个线程同时检测到 Token 过期时,如果没有防护措施,可能出现:
  3. 线程 A 开始刷新 Token
  4. 线程 B 也发起刷新请求
  5. 线程 C 使用已失效的旧 Token
  6. 可见性问题:刷新后的新 Token 可能无法立即被其他线程感知

解决方案大比拼

方案对比表

方案 优点 缺点
同步锁 实现简单 性能瓶颈
双重检查锁 减少锁竞争 实现复杂度高
消息队列 完全解耦 架构复杂度高

OkHttp 拦截器实现(Kotlin 版)

class TokenInterceptor : Interceptor {
    @Volatile private var isRefreshing = false
    private val lock = Any()

    override fun intercept(chain: Interceptor.Chain): Response {val request = chain.request()
        var response = proceedWithCurrentToken(chain, request)

        // Token 过期时自动刷新
        if (response.code == 401) {synchronized(lock) {if (isRefreshing) {lock.wait() // 等待刷新完成
                    return proceedWithNewToken(chain, request)
                } else {
                    isRefreshing = true
                    try {refreshTokenSync()
                        lock.notifyAll()} finally {isRefreshing = false}
                    response = proceedWithNewToken(chain, request)
                }
            }
        }
        return response
    }

    private fun refreshTokenSync() {// 实际刷新逻辑...}
}

生产环境避坑指南

  1. 刷新死锁:避免在刷新 Token 的请求中再次触发刷新
  2. 时钟漂移:客户端与服务端时间不同步导致提前判定 Token 失效
  3. 心跳间隔:建议设置为 Token 有效期的 1 /3

性能优化建议

  • 本地缓存 Token 时采用 SharedPreferencesapply()异步写入
  • 网络请求失败时采用指数退避重试策略
  • 对非关键路径请求可降级处理

思考题

在微服务架构下,当用户同时在手机和网页端登录时,如何保证多个设备的 Token 刷新不会互相覆盖?这个问题的解决方案可能会涉及到分布式锁的设计 …

正文完
 0
评论(没有评论)