Okhttp Authenticator多线程 [英] Okhttp Authenticator multithreading

查看:217
本文介绍了Okhttp Authenticator多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在具有几个异步请求的android应用程序中使用OkHttp.所有请求都要求令牌与标头一起发送.有时我需要使用RefreshToken刷新令牌,所以我决定使用OkHttpAuthenticator类.

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;
}

如何仅刷新令牌一次?

推荐答案

  1. 使用单例Authenticator

确保用于操作令牌的方法为Synchronized

Make sure the method you use to manipulate the token is Synchronized

计算重试次数以防止刷新次数过多 令牌呼叫

Count the number of retries to prevent excessive numbers of refresh token 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多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆