我正在制作一个基本应用程序来访问使用短期令牌作为 API 的 Twitch 服务器。因此,我使用 Retrofit 和 Hilt 创建了一个
okhttp3.Authenticator
类,用于处理添加令牌以进行身份验证,这与我在教程中甚至在 SO 中看到的其他几个非常相似。通常,当出现 401 秒时,会获取一个新令牌并将其添加到 newRequest 标头中的响应中,但由于某种原因,它在该阶段保持循环并因 too many requests
错误而中断。
这是一个与这个问题非常相似的问题,但即使在实施了公认的解决方案之后,它仍然会循环。
知道可能是什么问题吗?
我的身份验证器:
class AuthAuthenticator @Inject constructor(
private val sessionManager: SessionManager,
private val authApi: AuthApi
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
return runBlocking {
// call login api again for getting accessToken
val apiResponse = getNewToken()
if (apiResponse.isSuccessful) {
val accessToken = apiResponse.body()?.token ?: return@runBlocking null
val expireTime = apiResponse.body()?.expireTime ?: return@runBlocking null
accessToken.let {
sessionManager.saveToken(accessToken, expireTime)
}
response
.request
.newBuilder()
.header("Authorization", "Bearer $accessToken")
.build()
} else {
null
}
}
}
private suspend fun getNewToken(): retrofit2.Response<TokenResponse> {
return authApi.getAuthToken(
clientId = ExternalInfoHelper.valuesMap()[ApiValues.clientIdKey] ?: "",
clientSecret = ExternalInfoHelper.valuesMap()[ApiValues.clientSecretKey] ?: "",
grantType = ExternalInfoHelper.valuesMap()[ApiValues.grantTypeKey] ?: "" )
}
}
我像这样初始化 okhttp 客户端,使用一些 DI 来处理不同的改造客户端,因为 URL 不同:
private fun createOkHttpClient(
authInterceptor: AuthInterceptor?,
authAuthenticator: AuthAuthenticator?
): OkHttpClient {
val loggerInterceptor = HttpLoggingInterceptor()
loggerInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
val okhttp = OkHttpClient.Builder()
.addInterceptor(loggerInterceptor)
authAuthenticator?.let {
okhttp.authenticator(it)
}
authInterceptor?.let {
okhttp.addInterceptor(it)
} return okhttp.build()
}
这是我的拦截器,用于添加存储的令牌:
class AuthInterceptor @Inject constructor(private val sessionManager: SessionManager) :
Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = runBlocking {
sessionManager.getToken().first()
}
val request = chain.request().newBuilder()
request.addHeader(ApiValues.authHeaderKey, ApiValues.authHeaderValue.plus(token))
return chain.proceed(request.build())
}
}
我尝试用几种不同的方式重写代码,返回 null 并且不会改变循环。 使用从 Postman 获得的硬编码值返回请求会在日志中出现
too many requests
错误,而实际上没有执行任何请求
首先,验证 AuthAuthenticator 类是否已正确注入并由 Hilt 提供。确保依赖项 SessionManager 和 AuthApi 已正确注入并可用。
接下来,让我们仔细看看您的
中的authenticate功能AuthAuthenticator class:
override fun authenticate(route: Route?, response: Response): Request? {
return runBlocking {
// call login api again for getting accessToken
val apiResponse = getNewToken()
if (apiResponse.isSuccessful) {
// ... code to save and set the new access token ...
response
.request
.newBuilder()
.header("Authorization", "Bearer $accessToken")
.build()
} else {
null
}
}
}
根据您提供的代码片段,您似乎缺少更新的请求对象的分配。 response.request.newBuilder() 方法创建一个新的请求构建器,但您需要将其分配回response.request,以便使用新的访问令牌标头更新请求。修改代码如下:
override fun authenticate(route: Route?, response: Response): Request? {
return runBlocking {
// call login api again for getting accessToken
val apiResponse = getNewToken()
if (apiResponse.isSuccessful) {
// ... code to save and set the new access token ...
response
.request
.newBuilder()
.header("Authorization", "Bearer $accessToken")
.build()
} else {
null
}
}
}