我正在使用 Authenticator (而不是 Interceptor )来刷新令牌。我能够检测到401异常并轻松刷新新令牌。一切运行正常,但问题出在以下地方:
我无法再次调用该请求,我不希望用户再次点击以调用该报价。
因此,执行下面的代码后,我得到了一个新的令牌,它给了我401错误消息。 我的问题是:如何再次调用请求链? 欢迎提供任何有关实施的建议。
OffersViewModel类
val observable = ApiServiceClient.createApiUsingToken(context).getOffers(
Pref.getString(getApplication(), Pref.CUSTOMER_CODE, "")!!,
Pref.getString(getApplication(), Pref.TOKEN, "")!!
)
compositeDisposable.add(observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
responseModel.statusCode = StatusCode.START
offersRegisteredUserResponseLiveData.postValue(responseModel)
}
.subscribe({ success ->
if (success.errors.isNullOrEmpty()) {
success.statusCode = StatusCode.SUCCESS
} else {
success.statusCode = StatusCode.ERROR
}
offersRegisteredUserResponseLiveData.value = success
}, {
//HERE I GOT 401
Log.d("debug",it.message.toString())
responseModel.statusCode = StatusCode.ERROR
offersRegisteredUserResponseLiveData.value = responseModel
}, { })
)
API服务类
/*.....Offer Screen...........*/
@GET("offers/xyz/{abc}")
fun getOffers(
@Path("abc") customerCode: String,
@Header("Authorization") authorization: String,
@Header("Content-Type") contentType: String = CONTENT_TYPE
):
Observable<OfferRegisteredUserResponseModel>
ApiClient类
fun createApiUsingToken(context: Context?): ApiService {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder().addInterceptor(interceptor).connectTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.authenticator(TokenInterceptor(context)).build()
val retrofit = Retrofit.Builder()
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(Constants.BASE_URL)
.build()
var ApiServiceClient=retrofit.create(ApiService::class.java)
return retrofit.create(ApiService::class.java)
}
类TokenInterceptor
var requestAvailable: Request? = null
if (response!!.code() === 401) {
var retrofitResponse = ApiServiceClient.createToken().getTokenWithoutObserver().execute()
if (retrofitResponse != null) {
val refreshTokenResponse = retrofitResponse!!.body()
val newAccessToken = refreshTokenResponse!!.token
if (newAccessToken != null)
{
Pref.setString(MyApplication.mInstance, Pref.TOKEN, "${refreshTokenResponse.tokenType} ${refreshTokenResponse?.token}")
Pref.setString(MyApplication.mInstance, Pref.TOKEN_EXPIRES_IN, refreshTokenResponse.tokenExpirationTime.toString())
Utils.addTokenExpirationTimeToCurrentTime(MyApplication.mInstance, refreshTokenResponse.tokenExpirationTime?.toInt()!!)
try {
requestAvailable = response?.request()?.newBuilder()
?.addHeader("Content-Type", "application/json")
?.addHeader("Authorization", "Bearer " + newAccessToken)
?.build()
return requestAvailable
} catch (ex: Exception) {
}
}
} else
return null
}
return requestAvailable
答案 0 :(得分:0)
我认为事情错了。
首先是,即使您使用新令牌“重新启动”请求,如果恰好在未保存“新令牌”的情况下再次发出请求,该请求也将失败。
第二个是我看不到您将新令牌保存在任何地方(例如,在SharedPrefs中供以后使用)。
这就是我要做的:(preferenceHelper是SharedPrefs)
override fun authenticate(route: Route?, response: Response): Request? {
val HEADER_AUTHORIZATION = "Authorization"
// We need to have a token in order to refresh it.
val token = preferenceHelper.getAccessToken() ?: return null
synchronized(this) {
val newToken = preferenceHelper.getAccessToken() ?: return null
// Check if the request made was previously made as an authenticated request.
if (response.request().header(HEADER_AUTHORIZATION) != null) {
// If the token has changed since the request was made, use the new token.
if (newToken != token) {
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + newToken)
.build()
}
val tokenResponse = ApiServiceClient.createToken().getTokenWithoutObserver().execute()
if (tokenResponse.isSuccessful) {
val userToken = tokenResponse.body() ?: return null
preferenceHelper.saveAccessToken(userToken.token)
preferenceHelper.saveRefreshToken(userToken.refreshToken)
// Retry the request with the new token.
return response.request()
.newBuilder()
.removeHeader(HEADER_AUTHORIZATION)
.addHeader(HEADER_AUTHORIZATION, "Bearer " + userToken.token)
.build()
} else {
logoutUser()
}
}
}
return null
}