首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RefreshToken在ktor中未按预期工作

RefreshToken在ktor中未按预期工作
EN

Stack Overflow用户
提问于 2022-04-20 20:46:21
回答 1查看 461关注 0票数 0

嘿我在KMM的Ktor工作。我尝试使用refreshToken作为在我的应用程序中进行身份验证的建议。

HttpClient.kt

代码语言:javascript
复制
package com.example.kotlinmultiplatformsharedmodule

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
import java.util.concurrent.TimeUnit

actual fun httpClient(config: HttpClientConfig<*>.() -> Unit) = HttpClient(OkHttp) {
    config(this)
    install(Logging) {
        logger = Logger.SIMPLE
        level = LogLevel.BODY
    }
    install(ContentNegotiation) {
        json(Json {
            prettyPrint = true
            ignoreUnknownKeys = true
            explicitNulls = false
        })
    }
    engine {
        config {
            retryOnConnectionFailure(true)
            connectTimeout(30, TimeUnit.SECONDS)
            readTimeout(40, TimeUnit.SECONDS)
        }
    }
    defaultRequest {
        header("Client-Version", Platform().versionCode)
    }
    install(Auth) {
        bearer {
            loadTokens {
                BearerTokens(tokenProvider.accessToken, "")
            }
            refreshTokens {
                val response =
                    client.post("https://vivek-modi.com/api/v1/session/refresh") {
                        contentType(ContentType.Application.Json)
                        setBody(KtorSessionCommand(tokenProvider.refreshToken))
                    }
                if (response.status == HttpStatusCode.Unauthorized) {
                    println("application will logout")
                    null
                } else {
                    println("application in else part")
                    val ktorLoginResponse = response.body<KtorLoginResponse>()
                    ktorLoginResponse.ktorAccessToken?.let { ktorAccessToken ->
                        ktorAccessToken.accessToken?.let { accessToken ->
                            ktorAccessToken.refreshToken?.let { refreshToken ->
                                BearerTokens(accessToken, refreshToken)
                            }
                        }
                    }
                }
            }
        }
    }
}

build.gradle.kts

代码语言:javascript
复制
plugins {
    kotlin("multiplatform")
    kotlin("native.cocoapods")
    id("com.android.library")
    id("kotlinx-serialization")
}

version = "1.0"

kotlin {
    android()
    iosX64()
    iosArm64()
    iosSimulatorArm64()

    cocoapods {
        summary = "Some description for the Shared Module"
        homepage = "Link to the Shared Module homepage"
        ios.deploymentTarget = "14.1"
        framework {
            baseName = "kotlinmultiplatformsharedmodule"
        }
    }

    sourceSets {
        val ktorVersion = "2.0.0"
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-client-logging:$ktorVersion")
                implementation("io.ktor:ktor-server-default-headers:$ktorVersion")
                implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
                implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
                implementation("io.ktor:ktor-client-auth:$ktorVersion")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.3.2")
                implementation("io.insert-koin:koin-core:3.2.0-beta-1")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
                implementation("io.ktor:ktor-client-logging-jvm:$ktorVersion")
            }
        }
        val androidTest by getting
        val iosX64Main by getting
        val iosArm64Main by getting
        val iosSimulatorArm64Main by getting
        val iosMain by creating {
            dependsOn(commonMain)
            iosX64Main.dependsOn(this)
            iosArm64Main.dependsOn(this)
            iosSimulatorArm64Main.dependsOn(this)
            dependencies {
                implementation("io.ktor:ktor-client-darwin:$ktorVersion")
                implementation("io.ktor:ktor-client-logging-native:$ktorVersion")
            }
        }
        val iosX64Test by getting
        val iosArm64Test by getting
        val iosSimulatorArm64Test by getting
        val iosTest by creating {
            dependsOn(commonTest)
            iosX64Test.dependsOn(this)
            iosArm64Test.dependsOn(this)
            iosSimulatorArm64Test.dependsOn(this)
        }
    }
}

android {
    compileSdk = 32
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 21
        targetSdk = 32
    }
}

预期输出

场景1

当我的主api返回401时,如果返回与401状态不同,则需要调用https://vivek-modi.com/api/v1/session/refresh,然后再次调用主api。

场景2

当我的主api返回401时,如果返回401,我需要调用https://vivek-modi.com/api/v1/session/refresh,我需要注销我的应用程序。

实际输出

我在点击按钮调用api。

  1. 所以当我点击第一次按钮,它调用我的主api,它返回401。因此,refreshToken调用https://vivek-modi.com/api/v1/session/refresh,返回401。我使用println在控制台中打印消息,但它没有打印消息。

  1. 当我点击第二次或更多的时间按钮。它只调用我的主要api。它没有调用我的刷新api。

有人能指点我吗。我怎样才能实现我的预期产出。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-21 08:56:21

问题是客户端(特别是Auth插件)试图无限刷新令牌。下面是对应问题的评论

当刷新令牌请求与401失败时,它将再次尝试刷新令牌,从而导致无限循环。因为令牌刷新是用户的代码,用户需要标记这样的请求,所以我们可以有一个特例。

要解决这个问题,需要在请求生成器中调用markAsRefreshTokenRequest()

代码语言:javascript
复制
val response =
    client.post("https://vivek-modi.com/api/v1/session/refresh") {
        markAsRefreshTokenRequest()
        contentType(ContentType.Application.Json)
        setBody(KtorSessionCommand(tokenProvider.refreshToken))
    }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71946014

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档