W mojej aplikacji zaimplementowałem Retrofit do wywołania WebServices i używam OkHttp do używania Interceptor i Authenticator. Niektóre żądania wymagają token i mam zaimplementowany interfejs Authenticator do obsługi odświeżania (zgodnie z oficjalnym documentation). Ale mam następujący problem: od czasu do czasu w mojej aplikacji muszę wywołać więcej niż jedno żądanie naraz. Z tego powodu dla jednego z nich będę miał błąd 401.OkHttp i Retrofit, odświeżenie tokena z jednoczesnymi żądaniami
Oto mój kod dla połączeń żądanie:
public static <S> S createServiceAuthentication(Class<S> serviceClass, boolean hasPagination) {
final String jwt = JWT.getJWTValue(); //Get jwt value from Realm
if (hasPagination) {
Gson gson = new GsonBuilder().
registerTypeAdapter(Pagination.class, new PaginationTypeAdapter()).create();
builder =
new Retrofit.Builder()
.baseUrl(APIConstant.API_URL)
.addConverterFactory(GsonConverterFactory.create(gson));
}
OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
httpClient.addInterceptor(new AuthenticationInterceptor(jwt));
httpClient.authenticator(new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
if (responseCount(response) >= 2) {
// If both the original call and the call with refreshed token failed,
// it will probably keep failing, so don't try again.
return null;
}
if (jwt.equals(response.request().header("Authorization"))) {
return null; // If we already failed with these credentials, don't retry.
}
APIRest apiRest = createService(APIRest.class, false);
Call<JWTResponse> call = apiRest.refreshToken(new JWTBody(jwt));
try {
retrofit2.Response<JWTResponse> refreshTokenResponse = call.execute();
if (refreshTokenResponse.isSuccessful()) {
JWT.storeJwt(refreshTokenResponse.body().getJwt());
return response.request().newBuilder()
.header(CONTENT_TYPE, APPLICATION_JSON)
.header(ACCEPT, APPLICATION)
.header(AUTHORIZATION, "Bearer " + refreshTokenResponse.body().getJwt())
.build();
} else {
return null;
}
} catch (IOException e) {
return null;
}
}
});
builder.client(httpClient.build());
retrofit = builder.build();
return retrofit.create(serviceClass);
}
private static int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
Sprawa jest prosta, pierwsza prośba zostanie odświeżona token pomyślnie, ale inni będą powiodła się, ponieważ będą one odśwież token już odświeżony. WebService zwraca błąd 500. Czy istnieje jakieś eleganckie rozwiązanie, aby tego uniknąć?
Dziękujemy!
To może ci pomóc, mam nadzieję, że nie jest za późno https://stackoverflow.com/a/48518733/8187386 –