【问题标题】:Ktor Multiplatform Bearer Token Refresh leads to "mutation attempt of frozen kotlin.native.internal.Ref"Ktor Multiplatform Bearer Token Refresh 导致“冻结 kotlin.native.internal.Ref 的突变尝试”
【发布时间】:2022-01-19 16:42:58
【问题描述】:

我正在尝试让 Ktor 客户端刷新 Kotlin 多平台项目中的 Bearer 令牌。

有一个示例 here 它应该如何工作。

我的 http 客户端配置代码看起来非常相似 - 除了获取和刷新令牌的不同请求:

...
install(Auth) {
    lateinit var tokenInfo: TokenInfo
    var refreshTokenInfo: TokenInfo

    bearer {
        loadTokens {
            val url = "https://${environment.host}:${environment.port}/oauth/login"
            tokenInfo = tokenClient.post<TokenInfo>(url) {
                contentType(ContentType.Application.Json)
                body = buildJsonObject {
                    put("username", "blah")
                    put("password", "blub")
                }
            }
            BearerTokens(
                accessToken = tokenInfo.data.access_token,
                refreshToken = tokenInfo.data.refresh_token
            )
        }
        refreshTokens {
            val url = "https://${environment.host}:${environment.port}/oauth/refresh"
            refreshTokenInfo = tokenClient.get<TokenInfo>(url) {
                contentType(ContentType.Application.Json)
                header(HttpHeaders.Authorization, tokenInfo.data.refresh_token)
            }
            BearerTokens(
                accessToken = refreshTokenInfo.data.access_token,
                refreshToken = refreshTokenInfo.data.access_token
            )
        }
    }
}

但这会导致mutation attempt of frozen kotlin.native.internal.Ref。 好像不喜欢lateinit var tokenInfo: TokenInfo

这只发生在 iOS 上。 Android 工作正常。

(顺便说一句,我切换到new memory model。但在这种情况下,这似乎无关紧要,这是同样的错误。)

【问题讨论】:

标签: kotlin kotlin-multiplatform ktor kotlin-multiplatform-mobile kmm


【解决方案1】:

(A) 解决方案(对我而言)是使用 @Philip Dukhov 指出的内容:Atomics(我想我应该认真阅读,而不是一开始就略读。)

所以我使用AtomicReference 向 TokenInfo 添加了一个包装器:

object AtomicTokenInfo {
    val ref = AtomicReference(TokenInfo(Data(""), listOf()).freeze())

    fun storeNewValue(tokenInfo: TokenInfo) {
         ref.value = TokenInfo(tokenInfo.data, listOf()).freeze()
    }
}

然后在我的代码中使用它:

    var tokenInfo = AtomicTokenInfo

    ...

    val url = "https://${environment.host}:${environment.port}/oauth/refresh"
    tokenInfo.storeNewValue(
         tokenClient.get<TokenInfo>(url) {
             contentType(ContentType.Application.Json)
             header(HttpHeaders.Authorization, tokenInfo.ref.value.data.access_token)
         }
    )

非常感谢您的 cmets 和帮助@WhiteSpidy、@Philip Dukhov、@Aleksei Tirman

【讨论】:

    猜你喜欢
    • 2019-05-14
    • 2021-08-18
    • 1970-01-01
    • 2021-08-30
    • 2017-10-12
    • 1970-01-01
    • 2015-09-25
    • 2019-02-18
    • 2012-08-02
    相关资源
    最近更新 更多