1

我有一个 KMM 项目,其中我一直在使用 Ktor 进行 API 调用。我有一个要求,如果它们已过期,我需要在刷新令牌的帮助下更新我的访问令牌。基本上我只需要在我的 Ktor 客户端中添加一个身份验证模块。不,我已经浏览了所有Ktor 文档Auth并在我的 KMM 中添加了模块。

现在,当我在我的 http 客户端中添加身份验证模块时,它会成功添加,并且每当我UnAuthorized从任何 API 收到用户错误时,它都会调用我的刷新令牌 API。问题是即使它调用了我的刷新令牌 API,但在刷新令牌成功时,它不会调用我收到UnAuthorized用户错误的其他 API。

它在 Android 中按预期工作,但唯一的问题是在 iOS 客户端中。

预期(在 Android Http 客户端中工作正常):-

  • 调用任何 API -> 如果收到任何UnAuthorized用户错误调用刷新令牌 API -> 刷新令牌 API 的 onSuccess -> 使用更新的刷新令牌再次调用第一个 API。

我面临的问题:-

  • 调用任何 API -> 如果收到任何UnAuthorized用户错误,则调用刷新令牌 API -> onSuccess of refresh token API -> 在此步骤中什么也不做,只会从第一个 API 引发未经授权的用户错误。

HttpClient对于 iOS:-

actual class HttpBaseClient {

    actual val tokenClient = HttpClient {
        defaultRequest {
            host = ApiEndPoints.Base.url
            url {
                protocol = URLProtocol.HTTPS
            }
            contentType(ContentType.Application.Json)
            header(CONNECTION, CLOSE)
        }
        install(JsonFeature) {
            val json = kotlinx.serialization.json.Json {
                ignoreUnknownKeys = true
                coerceInputValues = true
            }
            serializer = KotlinxSerializer(json)
        }
    }

    actual val httpClient: HttpClient = HttpClient {
        defaultRequest {
            host = ApiEndPoints.Base.url
            url {
                protocol = URLProtocol.HTTPS
            }
            contentType(ContentType.Application.Json)
            header(CONNECTION, CLOSE)
        }
        // Validate Response
        expectSuccess = false
        // Install Auth
        install(Auth) {
            lateinit var refreshTokenInfo : LoginResponse
            bearer {
                refreshTokens { unauthorizedResponse: HttpResponse ->
                    NSLog("Unauthorized response received")
                    BaseAPIClass().refreshAuthToken().fold(
                        failed = {
                            // On Failed
                            NSLog("Token Failed"). // No Callback received here
                        },
                        succeeded = { response ->
                            refreshTokenInfo = response
                            NSLog("Token Updated") // No Callback received here even when API is success
                        }
                    )
                    BearerTokens(
                        accessToken = refreshTokenInfo.accessToken ?: "",
                        refreshToken = refreshTokenInfo.refreshToken ?: ""
                    )
                }
            }
        }
        // JSON Deserializer
        install(JsonFeature) {
            val json = kotlinx.serialization.json.Json {
                ignoreUnknownKeys = true
                coerceInputValues = true
            }
            serializer = KotlinxSerializer(json)
        }

Android客户端(几乎相同):-

actual class HttpBaseClient {

    actual val tokenClient = HttpClient {
        defaultRequest {
            host = ApiEndPoints.Base.url
            url {
                protocol = URLProtocol.HTTPS
            }
            contentType(ContentType.Application.Json)
            header(CONNECTION, CLOSE)
        }
        install(JsonFeature) {
            val json = kotlinx.serialization.json.Json {
                ignoreUnknownKeys = true
                coerceInputValues = true
            }
            serializer = KotlinxSerializer(json)
        }
        install(Logging) {
            logger = Logger.DEFAULT
            level = LogLevel.ALL
        }
    }

    actual val httpClient: HttpClient = HttpClient {
        defaultRequest {
            host = ApiEndPoints.Base.url
            url {
                protocol = URLProtocol.HTTPS
            }
            contentType(ContentType.Application.Json)
            header(CONNECTION, CLOSE)
        }
        // Validate Response
        expectSuccess = false
        //Authentication
        install(Auth) {
            lateinit var refreshTokenInfo : LoginResponse
            bearer {
                refreshTokens { unauthorizedResponse: HttpResponse ->
                    BaseAPIClass().refreshAuthToken().fold(
                        failed = {
                            // On Failed
                        },
                        succeeded = { response ->
                            refreshTokenInfo = response
                        }
                    )
                    BearerTokens(
                        accessToken = refreshTokenInfo.accessToken ?: "",
                        refreshToken = refreshTokenInfo.refreshToken ?: ""
                    )
                }
            }
        }

Ktor 版本:- 1.6.2(在阅读此问题后也尝试了 1.6.4,但没有成功)

4

1 回答 1

0

我得到这个工作只有错误是在这个代码: -

succeeded = { response ->
                        refreshTokenInfo = response
                        NSLog("Token Updated") // No Callback received here even when API is success
                    }

我不知道为什么,但是将响应分配给我lateinit var refreshTokenInfo是这里的主要问题。我删除了它并将我的代码更新为

refreshTokens { unauthorizedResponse: HttpResponse ->
                BaseAPIClass().refreshAuthToken().fold(
                    failed = {
                        // On Failed
                        return@refreshTokens BearerTokens(
                            accessToken = "",
                            refreshToken = ""
                        )
                    },
                    succeeded = { response ->
                      return@refreshTokens BearerTokens(
                            accessToken = response.accessToken ?: "",
                            refreshToken = response.refreshToken ?: ""
                        )
                    }
                )
            }

这有效。

我也在这里提出了这个问题,您可以查看详细信息。

于 2021-11-02T14:48:58.550 回答