我需要一些帮助。我正在运行拦截器来检测访问令牌是否过期。因此,如果过期,我将尝试刷新令牌,否则我会发送请求。
我的问题是,它正在运行标头带有令牌的刷新令牌请求,以及标头带有刷新令牌的其他请求。我查了一下,他们说是并发问题。因为我是新手,所以我认为我使用了错误的方法。
请任何人都可以帮助我解决这个问题。这是我的代码。
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 实现拦截器。我希望刷新令牌,然后之前的请求将自动启动。
最后我来回答我的问题。根据 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
}
}
}