如何处理平行API调用的刷新令牌

发布于 2025-01-17 18:33:10 字数 1323 浏览 3 评论 0原文

在一个视图中,我在并行mod中有多个API调用,当令牌过期时,所有这些都有401个,并且所有这些都有刷新的令牌。我应该如何保护自己免受此侵害。我听说过Mutex,但我真的不知道该怎么做。使用身份验证器或拦截器授权401授权或其他方法可以处理此问题?

我的身份验证者类。

class TokenAuthenticator( 
private val authenticationRepository: AuthenticationRepository, 
private val userAndTokenRepository: UserAndTokenRepository, 
private val crashlyticsManager: CrashlyticsManager 
) : Authenticator {

override fun authenticate(route: Route?, response: Response): Request? {
    return runBlocking {
        getUpdatedToken()?.let { token ->
            userAndTokenRepository.storeToken(token)
            response.request.newBuilder()
                .header(HEADER_AUTHORIZATION, "$AUTHORIZATION_TYPE ${token.accessToken}")
                .build()
        }
    }
}

private suspend fun getUpdatedToken(): Token? {
    return withContext(Dispatchers.IO) {
        val accessTokenResult = authenticationRepository.refresh(
            userAndTokenRepository.getEmail() ?: "",
            userAndTokenRepository.getRefreshToken() ?: ""
        )
        when (accessTokenResult) {
            is Result.Success -> accessTokenResult.data
            is Result.Failure -> {
                crashlyticsManager.recordException(Exception(accessTokenResult.error))
                null
            }
        }
    }
 }
}

I have multple API calls in Parallel Mod in one View, and when token is Expired all of them got 401, and authenticator refreshing token for all of them. how should I protect myself against this. I've heard about mutex but I don't really know how to do it with it. Is it better to authorize the 401 using Authenticator or interceptor or are there any other ways to handle this?

My authenticator class below.

class TokenAuthenticator( 
private val authenticationRepository: AuthenticationRepository, 
private val userAndTokenRepository: UserAndTokenRepository, 
private val crashlyticsManager: CrashlyticsManager 
) : Authenticator {

override fun authenticate(route: Route?, response: Response): Request? {
    return runBlocking {
        getUpdatedToken()?.let { token ->
            userAndTokenRepository.storeToken(token)
            response.request.newBuilder()
                .header(HEADER_AUTHORIZATION, "$AUTHORIZATION_TYPE ${token.accessToken}")
                .build()
        }
    }
}

private suspend fun getUpdatedToken(): Token? {
    return withContext(Dispatchers.IO) {
        val accessTokenResult = authenticationRepository.refresh(
            userAndTokenRepository.getEmail() ?: "",
            userAndTokenRepository.getRefreshToken() ?: ""
        )
        when (accessTokenResult) {
            is Result.Success -> accessTokenResult.data
            is Result.Failure -> {
                crashlyticsManager.recordException(Exception(accessTokenResult.error))
                null
            }
        }
    }
 }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

林空鹿饮溪 2025-01-24 18:33:10

这有一个很好的例子,只需使用同步化,因为您真的只希望一个人刷新令牌,而其他人应该等待。

https://blog.coinbase.com/okhttp-oauth-token-refreshes- B598F555DD3B2

class AccessTokenAuthenticator(
    private val tokenProvider: AccessTokenProvider
) : Authenticator {

    override fun authenticate(route: Route?, response: Response): Request? {
        // We need to have a token in order to refresh it.
        val token = tokenProvider.token() ?: return null

        synchronized(this) {
            val newToken = tokenProvider.token()

This has a good example, just using synchronized, since you really only want one to refresh the token, and other should wait.

https://blog.coinbase.com/okhttp-oauth-token-refreshes-b598f55dd3b2

class AccessTokenAuthenticator(
    private val tokenProvider: AccessTokenProvider
) : Authenticator {

    override fun authenticate(route: Route?, response: Response): Request? {
        // We need to have a token in order to refresh it.
        val token = tokenProvider.token() ?: return null

        synchronized(this) {
            val newToken = tokenProvider.token()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文