You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ktor IO客户端如何防止refreshTokens回调被多次重复调用

Ktor Bearer Auth 避免重复刷新Token的锁实现方案

你需要使用 Kotlin 协程专属的非阻塞互斥锁 Mutex 结合双重校验机制,解决并发场景下refreshTokens回调重复触发的问题,该方案不会阻塞线程,仅挂起等待的协程,适配Ktor的协程运行环境。

实现代码示例

首先引入协程同步依赖(已引入可跳过),并声明和HttpClient实例同生命周期的单例互斥锁:

import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

// 要和业务使用的HttpClient实例绑定,保证为单例
private val refreshTokenMutex = Mutex()

修改后的refreshTokens回调实现:

refreshTokens {
    val oldRefreshToken = preference.get(PreferenceKeys.REFRESH_TOKEN.key)
    // 第一层控制:同一时间仅允许一个协程进入刷新逻辑,其他协程挂起等待锁释放
    refreshTokenMutex.withLock {
        // 第二层校验:拿到锁后先判断Token是否已经被其他请求刷新完成
        val currentRefreshToken = preference.get(PreferenceKeys.REFRESH_TOKEN.key)
        if (currentRefreshToken != oldRefreshToken) {
            // 已被其他请求刷新,直接返回最新Token即可
            return@withLock BearerTokens(
                accessToken = preference.get(PreferenceKeys.ACCESS_TOKEN.key).orEmpty(),
                refreshToken = currentRefreshToken.orEmpty()
            )
        }

        // 未被刷新,执行实际的刷新请求逻辑
        val fullUrl = "$baseUrl/auth/token:refresh"
        val authData = tokenClient.post<AuthResponse>(fullUrl) {
            body = AuthResponse(null, oldRefreshToken)
            header(HttpHeaders.ContentType, ContentType.Application.Json)
        }

        // 刷新成功后先持久化新Token到本地存储
        preference.put(PreferenceKeys.ACCESS_TOKEN.key, authData.accessToken.orEmpty())
        preference.put(PreferenceKeys.REFRESH_TOKEN.key, authData.refreshToken.orEmpty())

        BearerTokens(
            accessToken = authData.accessToken ?: "",
            refreshToken = authData.refreshToken ?: ""
        )
    }
}

注意事项

  • refreshTokenMutex必须和业务使用的HttpClient实例绑定为单例,不要每次创建HttpClient都新建锁实例
  • 代码中的tokenClient建议为单独配置的HttpClient实例,不要添加Auth插件,避免刷新Token的请求本身触发401校验,导致循环刷新
  • 如果刷新Token时返回401等错误,说明refreshToken已失效,需要捕获异常主动清除本地Token,引导用户重新登录,避免锁被无效持有
  • 如果是多进程场景下使用,需要额外实现跨进程锁(比如基于文件锁、SharedPreferences事务锁),协程Mutex仅支持同一进程内的协程互斥

内容的提问来源于stack exchange,提问作者Narek Simonyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 08:45:01