我有一个类来处理令牌过期后的令牌刷新。代码如下:
public class TokenAuthenticator implements Authenticator {
@Nullable
@Override
public synchronized Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<User> call = apiInterface.refreshTokens(new ClientRequest(Songa.getContext().getString(R.string.client_id),
App.getContext().getString(R.string.client_secret),
App.getContext().getString(R.string.grant_type), getRAGUser().getRefreshToken()));
User ragUser = call.execute().body();
if (ragUser != null) {
Gson gson = new Gson();
String user = gson.toJson(ragUser);
PrefUtils.putString(Constants.USER, user);
long tokenExpiryPeriod = System.currentTimeMillis() + Long.parseLong(ragUser.getExpiryPeriod());
PrefUtils.putLong(Constants.TOKEN_EXPIRY_PERIOD, tokenExpiryPeriod);
return response.request().newBuilder().header("Authorization", "Bearer " + ragUser.getAccessToken()).build();
} else {
if (responseCount(response) >= 3) {
Log.e("TokenAuthenticator", String.valueOf(responseCount(response)));
//we have failed 3 times; log the user out
EventBus.getDefault().post(new LogoutEvent());
return null;
}
}
return null;
}
private int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
}
我的意图是,一旦令牌过期,验证者应该在放弃并注销用户之前最多重试三次。但是,即使使用有效的令牌,下面的代码也会执行三次请求。
我一直认为Authenticator
类仅在令牌过期时介入,但是从我的日志中,我可以看到每次发出新请求时都会调用它。
以下是我的Retrofit
客户端的代码:
public class RestClient {
private static final String BASE_URL = "https://my.base.url/api/v3/";
private static String token = "Bearer " + getAccessToken();
private static Retrofit retrofit = null;
public RestClient() {
}
public static Retrofit getClient() {
if (retrofit == null) {
TokenAuthenticator tokenAuthenticator = new TokenAuthenticator();
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}).create();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.authenticator(tokenAuthenticator)
.addInterceptor(loggingInterceptor)
.addInterceptor(chain -> {
Request original = chain.request();
Request request = original.newBuilder()
.addHeader("Authorization", token)
.addHeader("Content-Type", "application/json")
.build();
return chain.proceed(request);
})
.addInterceptor(loggingInterceptor)
.dispatcher(dispatcher)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okClient)
.build();
}
return retrofit;
}
}
是否有更好的方法可以根据我的要求实施令牌认证;注销前重试3次?