我是RxJava的新手,我尝试使用我的Android / Kotlin应用程序中的刷新令牌实现OAuth2流程。
我在拦截器中刷新访问令牌时遇到了一些困难(我为OAuthAuthenticator
内的每个API请求添加了访问令牌)。问题是我想等待填充请求,直到令牌请求完成。
有人会暗示我如何实现这个目标吗?
这是我的身份验证员类:
class OAuthAuthenticator(
private val authStateManager: AuthStateManager,
private val authRepository: AuthRepository): Authenticator {
override fun authenticate(route: Route?, response: Response?): Request? {
// handle invalid token
if (response != null && response.code() == 401) {
println("Invalid access token")
authRepository.refreshToken()
.subscribe { _ ->
println("Token refreshed")
}
}
// this should happen after the token request is completed since it would fail again otherwise
return response?.request()!!
.newBuilder()
.header("Authorization", "Bearer " + authStateManager.current.accessToken)
.build()
}
}
答案 0 :(得分:0)
您正在同步方法中进行异步调用。那不会奏效。在rx链中完成令牌请求后,您必须放置要执行的代码。
class OAuthAuthenticator(
private val authStateManager: AuthStateManager,
private val authRepository: AuthRepository) : Authenticator {
override fun authenticate(route: Route?, response: Response?): Single<Request> {
// handle invalid token
if (response != null && response.code() == 401) {
return Single.error(InvalidAccessTokenException("Invalid access token"))
}
return Single.fromCallable { authRepository.refreshAccessToken() }
.subscribeOn(Schedulers.computation())
.map {
return@map response?.request()!!
.newBuilder()
.header("Authorization", "Bearer " +
authStateManager.current.accessToken)
.build()
}
}
}
然后你可以这样称呼它:
val authenticator = OAuthAuthenticator(authStateManager, authRepository)
val disposable = authenticator.authenticate(route, response)
.subscribe({ _ ->
println("Token refreshed")
}, { error ->
if (error is InvalidAccessTokenException) {
println("Invalid access token")
} else {
println("Could not refresh token. Signing out...")
authStateManager.signOut()
}
})
答案 1 :(得分:0)
您可以使用blockingGet()
使Single
同步。但不建议这样做。但是,因为您使用
Single
Single.fromCallable { authRepository.refreshAccessToken() }
你可以直接调用适当的方法而不用 Rx 包装它。
if (response != null && response.code() == 401) {
println("Invalid access token")
try {
authRepository.refreshAccessToken()
println("Token refreshed")
} catch(error: Throwable) {
println("Could not refresh token. Signing out...")
authStateManager.signOut()
return null
}
}