簡體   English   中英

如何使用 retrofit android Kotlin 刷新 Bearer Token

[英]how to refresh Bearer Token using retrofit android Kotlin

雖然登錄應用程序我可以獲得令牌,刷新令牌並保存它但我不知道 session 何時結束令牌如何更新。 如何在其中添加攔截器以更新令牌或可以使用其他一些方法? 這是我的代碼

1- Api 端點

@POST("identity/Identity/GetRefreshToken")
suspend fun refreshToken(): AuthTokenEntityDT0

2- AuthTokenEntityDT0 響應

data class AuthTokenEntityDT0(
@SerializedName("accessToken") val accessToken: String,
@SerializedName("refreshToken") val refreshToken: String,
@SerializedName("statusCode") val statusCode: Int,
@SerializedName("statusMessage") val statusMessage: String,
)

3 - 在這里提出請求

@Provides
@Singleton
fun provideAPIService(): ApiService {
   val interceptor = HttpLoggingInterceptor()
   interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
   val client: OkHttpClient = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .addInterceptor { chain ->
                val original = chain.request()
                val requestBuilder = original.newBuilder()
                .addHeader("Content-Type", "application/json; charset=UTF-8")
                .addHeader("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
                .addHeader("Authorization", "Bearer $access_token")
                val request = requestBuilder.build()
                chain.proceed(request)
            }
            .build()


        val retrofit = Retrofit.Builder()
            .baseUrl(NativeBaseUrl.getBaseUrl())
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        return retrofit.create(ApiService::
        class.java)
    }


    @Provides
    fun provideApiRepository(apiService: ApiService): ApiRepository {
        return ApiRepositoryImpl(apiService)
    }

4 -

問題:refreshToken Api 反復調用我如何停止它並繼續前進,盡管我已將 Dispatcher 用於一個請求以像這樣前進

    val interceptor = HttpLoggingInterceptor()
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
    val dispatcher = Dispatcher()
    dispatcher.maxRequests = 1

    val client: OkHttpClient = OkHttpClient.Builder()
        .addInterceptor(ForbiddenInterceptor(this))
        .dispatcher(dispatcher)
        .addInterceptor(interceptor)
        .addInterceptor { chain ->
            val original = chain.request()
            val requestBuilder = original.newBuilder()
                .addHeader("Content-Type", "application/json; 
         charset=UTF-8")
                .addHeader("user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 
                  10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
                .addHeader("Authorization", "Bearer $access_token")
            val request = requestBuilder.build()
         chain.proceed(request)
        }
        .build()

5- 這是我的攔截器

class ForbiddenInterceptor(var hIltModules: HIltModules) : 
Interceptor {
@Throws(IOException::class)

override fun intercept(chain: Interceptor.Chain): Response {
    val original = chain.request()
    val response = chain.proceed(original)


    if (response.code == 401) {

        val responseRefreshTokens= runBlocking {
            val originalRequests = chain.request()
            val authenticationRequest = originalRequests.newBuilder()
                .addHeader("refreshtoken", "${Constants.refreshToken}").build()
            chain.proceed(authenticationRequest)

           hIltModules.provideAPIService().refreshToken()

        }

        if (responseRefreshTokens.statusCode == 200) {
            val originalRequests = chain.request()
            val newAuthenticationRequest = originalRequests.newBuilder()
                .removeHeader("refreshtoken")
                .build()

            access_token = responseRefreshTokens.accessToken
            refreshToken = responseRefreshTokens.refreshToken

            return chain.proceed(newAuthenticationRequest)

        }


    }
    return chain.proceed(original)
}

}

我建議你把你的自定義攔截器放在它自己的 class 中,像這樣:

class ForbiddenInterceptor : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        val response: Response = chain.proceed(request)
        if (response.code == 401) {
            // this code section will run for every HTTP 401 response
        }
        return response
    }
}

然后使用這個攔截器:

val client: OkHttpClient = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .addInterceptor(ForbiddenInterceptor())
            .build()

將攔截器添加到 OkHttpClient 確保您將攔截調用並且您可以運行自定義代碼,檢查它是否已被服務器拒絕。

至於更新你的令牌。 您可能需要實現后端的另一項服務。 我只能假設,但你必須使用你的accesToken將它提供給端點,服務器將返回一個新的refreshToken

這是我為刷新令牌所做的完整代碼,它可能對某些人有幫助

class AuthenticationInterceptorRefreshToken @Inject constructor(
var hIltModules: HIltModules,

) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {

    val originalRequest = chain.request()
    val response = chain.proceed(originalRequest)

    if (response.code == 401) {

        synchronized(this) {

            val originalRequest = chain.request()
            val authenticationRequest = originalRequest.newBuilder()
                .addHeader("refreshtoken", " $refreshToken")
                .build()
            val initialResponse = chain.proceed(authenticationRequest)

            when (initialResponse.code) {

                401 -> {
                    val responseNewTokenLoginModel = runBlocking {
                        hIltModules.provideAPIService().refreshToken()
                    }

                    when (responseNewTokenLoginModel.statusCode) {
                        200 -> {
                            refreshToken = responseNewTokenLoginModel.refreshToken
                            access_token = responseNewTokenLoginModel.accessToken

                            val newAuthenticationRequest = originalRequest.newBuilder()
                                .header("refreshtoken",
                                    " $refreshToken")
                                .build()
                            return chain.proceed(newAuthenticationRequest)
                        }
                        else -> {
                            return null!!
                        }
                    }
                }
                else -> return initialResponse
            }
        }
    }; return response
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM