Kotlin 中的 GraphQL 刷新令牌

问题描述 投票:0回答:1

我需要一些帮助。我正在运行拦截器来检测访问令牌是否过期。因此,如果过期,我将尝试刷新令牌,否则我会发送请求。

我的问题是,它正在运行标头带有令牌的刷新令牌请求,以及标头带有刷新令牌的其他请求。我查了一下,他们说是并发问题。因为我是新手,所以我认为我使用了错误的方法。

请任何人都可以帮助我解决这个问题。这是我的代码。

class ApolloInterceptor @Inject constructor(
    private val loginViewModel: Lazy<LoginViewModel>, private val context: Context, private var storage: Storage,
) : HttpInterceptor {
    private val mutex = Mutex()
    private var isRefreshTokenInProgress = false

    override suspend fun intercept(request: HttpRequest, chain: HttpInterceptorChain): HttpResponse {

        // retrieve current token and refresh token
        val token = mutex.withLock {
            storage.getString(SharedPreferencesStorage.TOKEN)
        }
        val refreshToken: String = mutex.withLock {
            storage.getString(SharedPreferencesStorage.REFRESH_TOKEN)
        }

        // convert token expiration date and now date to UTC
        val tokenExpirationDate = storage.getString(SharedPreferencesStorage.TOKEN_EXPIRATION_DATE)
        val tokenExpirationDateTime = LocalDateTime.parse(tokenExpirationDate)
        val nowDateTime = LocalDateTime.now()
        val tokenExpirationUtc = ZonedDateTime.of(tokenExpirationDateTime, ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC"))
        val currentDateTimeUtc = ZonedDateTime.of(nowDateTime, ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC"))


        val isTokenExpired = currentDateTimeUtc.isAfter(tokenExpirationUtc)


        if (isTokenExpired && !isRefreshTokenInProgress) {
            // refresh token
            mutex.withLock {
                isRefreshTokenInProgress = true
                loginViewModel.get().refreshToken().join()
                return chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $refreshToken").build())
            }
        } else {
            // otherwise send request
            mutex.withLock {
                val requestBuilder = request.newBuilder()
                val response = chain.proceed(requestBuilder.addHeader("Authorization", "Bearer $token").build())
                val versionName = BuildConfig.VERSION_NAME
                val versionCode = BuildConfig.VERSION_CODE
                requestBuilder.addHeader("version", versionName)
                requestBuilder.addHeader("build", versionCode.toString())
                requestBuilder.addHeader("User-Agent", getDefaultUserAgent())
                requestBuilder.addHeader("language", getDeviceLanguage())
                requestBuilder.addHeader("theme", if (isDarkModeActive(context)) "dark" else "light")
                Log.e("TAG", "intercept: dkhal request")
                isRefreshTokenInProgress = false
                return response
            }
        }
    }
}

我尝试使用 Mutex.withLock 并研究了如何为 Apollo 实现拦截器。我希望刷新令牌,然后之前的请求将自动启动。

android kotlin graphql apollo
1个回答
0
投票

最后我来回答我的问题。根据 Apollo 文档,您需要执行以下操作。它在我的代码中就像一个魅力。我希望它可以帮助别人。

class AuthorizationInterceptor() : HttpInterceptor {
private val mutex = Mutex()

override suspend fun intercept(request: HttpRequest, chain:         
HttpInterceptorChain): HttpResponse {
var token = mutex.withLock {
  // get current token
}

val response = chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $token").build())

return if (response.statusCode == 401) {
  token = mutex.withLock {
    // get new token
  }
  chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $token").build())
} else {
  response
  }
 }
}
© www.soinside.com 2019 - 2024. All rights reserved.