Android 中,Claude Code 如何处理 token 失效 401

比如以下这个场景:

/**
 * 认证拦截器
 * 负责在请求头中添加Token,并处理401未授权响应
 *
 * 注意:OkHttp拦截器运行在网络线程,路由跳转需要切换到主线程执行
 */
class AuthInterceptor(
    private val context: Context,
    private val tokenProvider: () -> String?
) : Interceptor {

    companion object {
        // 防止多个401响应同时触发多次跳转登录页
        private val isHandlingUnauthorized = AtomicBoolean(false)

        // 主线程Handler,用于切换线程执行路由跳转
        private val mainHandler = Handler(Looper.getMainLooper())
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val token = tokenProvider()

        val request = chain.request().newBuilder().apply {
            token?.let { header("Authorization", "Bearer $it") }
        }.build()

        val response = chain.proceed(request)

        // 如果返回401,代表token失效
        if (response.code == 401) {
            handleUnauthorized()
        }

        return response
    }

    /**
     * 处理401未授权响应
     * 使用AtomicBoolean确保并发情况下只执行一次
     * 切换到主线程执行路由跳转,避免TheRouter的ConcurrentModificationException
     */
    private fun handleUnauthorized() {
        // 使用CAS操作确保只有一个线程能够执行跳转逻辑
        if (isHandlingUnauthorized.compareAndSet(false, true)) {
            // 切换到主线程执行,避免TheRouter并发问题
            mainHandler.post {
                try {
                    // 清除本地token
                    CommonUtil.exitClearAccount()
                    // 跳转登录页
                    WrapperIntentUtil.toActivity(ARouterConfig.MainRouterConst.PHONE_LOGIN_HOST)
                } finally {
                    // 延迟重置标志位,避免短时间内重复触发
                    mainHandler.postDelayed({
                        isHandlingUnauthorized.set(false)
                    }, 2000)
                }
            }
        }
    }
}

问题原因:

  • OkHttp 的拦截器运行在网络线程池中
  • 当多个网络请求同时返回 401 时,多个线程并发调用 TheRouter 的路由跳转
  • TheRouter 内部的 SimpleArrayMap 不是线程安全的,导致 ConcurrentModificationException

解决方案:

  1. 切换到主线程执行路由跳转
    mainHandler.post {
    // 路由跳转代码
    }
  2. 使用 AtomicBoolean 防止重复跳转
    private val isHandlingUnauthorized = AtomicBoolean(false)

// CAS操作确保只有一个线程能执行
if (isHandlingUnauthorized.compareAndSet(false, true)) {
// 执行跳转逻辑
}

  1. 延迟重置标志位
- 2秒后重置 isHandlingUnauthorized,避免短时间内重复触发

这样修改后:

  • 路由跳转在主线程执行,避免了 TheRouter 的并发问题
  • 即使有多个 401 响应同时到达,也只会触发一次跳转登录页
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容