问题描述
我在具有几个异步请求的android应用程序中使用OkHttp
.所有请求都要求令牌与标头一起发送.有时我需要使用RefreshToken刷新令牌,所以我决定使用OkHttp
的Authenticator
类.
I am using OkHttp
in my android application with several async requests. All requests require a token to be sent with the header. Sometimes I need to refresh the token using a RefreshToken, so I decided to use OkHttp
's Authenticator
class.
当两个或多个异步请求同时从服务器获得401响应代码时,会发生什么?是对每个请求调用Authenticator的authenticate()
方法,还是对第一个获得401的请求仅调用一次?
What will happen when 2 or more async requests get a 401 response code from the server at the same time? Would the Authenticator's authenticate()
method be called for each request, or it will only called once for the first request that got a 401?
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException
{
return null;
}
如何仅刷新令牌一次?
推荐答案
-
使用单例
Authenticator
确保用于操作令牌的方法为Synchronized
Make sure the method you use to manipulate the token is Synchronized
计算重试次数以防止刷新次数过多令牌呼叫
Count the number of retries to prevent excessive numbers of refreshtoken calls
这里是科特林的一个样本
Here is a sample in Kotlin
@SingleTon
class TokenAuthenticator @Inject constructor(
private val tokenRepository: TokenRepository
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
return if (isRequestRequiresAuth(response)) {
val request = response.request()
authenticateRequestUsingFreshAccessToken(request, retryCount(request) + 1)
} else {
null
}
}
private fun retryCount(request: Request): Int =
request.header("RetryCount")?.toInt() ?: 0
@Synchronized
private fun authenticateRequestUsingFreshAccessToken(
request: Request,
retryCount: Int
): Request? {
if (retryCount > 2) return null
tokenRepository.getAccessToken()?.let { lastSavedAccessToken ->
val accessTokenOfRequest = request.header("Authorization") // Some string manipulation needed here to get the token if you have a Bearer token
if (accessTokenOfRequest != lastSavedAccessToken) {
return getNewRequest(request, retryCount, lastSavedAccessToken)
}
}
tokenRepository.getFreshAccessToken()?.let { freshAccessToken ->
return getNewRequest(request, retryCount, freshAccessToken)
}
return null
}
private fun getNewRequest(request: Request, retryCount: Int, accessToken: String): Request {
return request.newBuilder()
.header("Authorization", "Bearer " + accessToken)
.header("RetryCount", "$retryCount")
.build()
}
private fun isRequestRequiresAuth(response: Response): Boolean {
val header = response.request().header("Authorization")
return header != null && header.startsWith("Bearer ")
}
}
这篇关于Okhttp Authenticator多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!