我正在为我的项目中的网络使用改造。问题是我必须在第一个活动中调用2个请求。它工作正常,但是当访问令牌过期时,它必须刷新令牌。我已经使用okhttp Authenticator实现了呼叫。但是它多次调用,并且此错误也显示too many followup request 21
EDIT
我更新了TokenAuthenticator类并添加了synced()。但它是从if (originalRequest.header("Authorization") != null) return null
返回的。我正在关注这个答案https://stackoverflow.com/a/52513122/10243953
如果我要删除if (originalRequest.header("Authorization") != null) return null
这行,那么它会起作用,但是在日志报告中,我会看到它多次要求刷新令牌。我如何避免多次打来电话?
这是我的Authenticator类
class TokenAuthenticator : Authenticator {
private val refreshTokenGrandType = "refresh_token"
private var oldToken: String? = null
private var newToken: String? = null
override fun authenticate(route: Route?, response: Response?): Request? {
oldToken = SharedPreferenceManager(MainApplication.applicationContext()).getToken()
if (response == null) return null
val originalRequest = response.request()
if (originalRequest.header("Authorization") != null) return null
if(!isTokenSaved()){
synchronized(this) {
RetrofitClient.client.create(Auth::class.java).refresh_token(
SharedPreferenceManager(MainApplication.applicationContext()).getRefreshToken()!!,
refreshTokenGrandType
).enqueue(object : Callback<Token> {
override fun onFailure(call: Call<Token>, t: Throwable) {
Toast.makeText(
MainApplication.applicationContext(),
t.message,
Toast.LENGTH_SHORT
).show()
Log.d("TokenAuth", t.message!!)
}
override fun onResponse(
call: Call<Token>,
response: retrofit2.Response<Token>
) {
if (response.isSuccessful) {
val body = response.body()
newToken = body!!.access_token
val refresh_token = body.refresh_token
SharedPreferenceManager(MainApplication.applicationContext()).accessToken(
newToken!!,
refresh_token
)
} else {
val error = response.errorBody()
Log.d("TokenAuthRes", error!!.string())
}
}
})
}
}
return originalRequest
.newBuilder()
.header(
"Authorization",
"Bearer ${SharedPreferenceManager(MainApplication.applicationContext()).getToken()}"
)
.build()
}
fun isTokenSaved() : Boolean{
if (newToken == null) return false
if (oldToken.equals(newToken)) return false
else return true
}
}
改造客户端
object RetrofitClient {
private lateinit var interceptor : Interceptor
private lateinit var okHttpClient: OkHttpClient
private var retrofit : Retrofit? = null
val client : Retrofit
get(){
val context : Context = MainApplication.applicationContext()
interceptor = Interceptor { chain ->
val url = chain.request()
.url()
.newBuilder()
.build()
val request = chain.request()
.newBuilder()
.addHeader("Authorization","Bearer ${SharedPreferenceManager(context).getToken()}")
.url(url)
.build()
return@Interceptor chain.proceed(request)
}
okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(NoInternetInterception(context))
.authenticator(TokenAuthenticator())
.connectTimeout(1, TimeUnit.MINUTES)
.build()
if (retrofit == null){
retrofit = Retrofit.Builder()
.client(okHttpClient)
.baseUrl(const.URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
return retrofit!!
}
}
答案 0 :(得分:1)
在您的TokenAuthenticator
中尝试一下:
override fun authenticate(route: Route, response: Response): Request? {
val call = RetrofitClient.client.create(Auth::class.java).refresh_token(SharedPreferenceManager(MainApplication.applicationContext()).getRefreshToken()!!,refreshTokenGrandType)
val refreshResponse = call.execute()
if (refreshResponse.isSuccessful()) {
//Save your new token
return response
.request()
.newBuilder()
.header(
"Authorization",
"Bearer ${SharedPreferenceManager(MainApplication.applicationContext()).getToken()}"
)
.build()
} else return null
}