2016-06-11 8 views
7

Używam Retrofit 2.0 z konwerterem Jackson do komunikacji z interfejsem API Rest. Niektóre z żądań wymagają tokenów po autoryzacji. Jeśli posiadane przeze mnie tokeny są nieaktualne, muszę odświeżyć je za pomocą innego żądania i powtórzyć ostatnie żądanie, które nie powiodło się z tego powodu.Android Retrofit 2.0 Odświeżenie tokenów

Moje pytanie: czy muszę robić to ręcznie za każdym razem, czy jest jakiś sposób na zautomatyzowanie go?

Oto sposób zaimplementować go w tej chwili:

TrackerService

public interface TrackerService { 

    @POST("auth/sendPassword") 
    Call<ResponseMessage> sendPassword(@Header("app-type") String appType, 
             @Body User userMobile); 

    @FormUrlEncoded 
    @POST("oauth/token") 
    Call<TokenResponse> oathToken(@Field("client_id") String clientId, 
            @Field("client_secret") String clientSecret, 
            @Field("grant_type") String grantType, 
            @Field("username") String username, 
            @Field("password") String password); 

    @FormUrlEncoded 
    @POST("oauth/token") 
    Call<TokenResponse> refreshToken(@Field("client_id") String clientId, 
            @Field("client_secret") String clientSecret, 
            @Field("grant_type") String grantType, 
            @Field("refresh_token") String username); 


    @PUT("me/profile") 
    Call<Profile> updateProfile(@Header("app-type") String appType, 
           @Header("Authorization") String token, 
           @Body Profile profile); 

} 

ServiceGateway

public class ServiceGateway { 

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 
    private static Retrofit retrofit; 

    public static <S> S createService(Class<S> serviceClass) { 
     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient client = new OkHttpClient.Builder() 
       .connectTimeout(20 * 1000, TimeUnit.MILLISECONDS) 
       .writeTimeout(20 * 1000, TimeUnit.MILLISECONDS) 
       .readTimeout(20 * 1000, TimeUnit.MILLISECONDS) 
       .addInterceptor(interceptor).build(); 

     Retrofit.Builder builder = 
       new Retrofit.Builder() 
         .baseUrl(BASE_URL) 
         .addConverterFactory(JacksonConverterFactory.create()); 

     retrofit = builder.client(httpClient.build()) 
       .client(client) 
       .build(); 
     return retrofit.create(serviceClass); 
    } 

    public static Retrofit getRetrofit() { 
     return retrofit; 
    } 
} 

Jak zgłoszę funkcji i traktować go, gdy tokeny są nieaktualny

trackerService = ServiceGateway.createService(TrackerService.class); 

    Call<Profile> call = trackerService.updateProfile(getString(R.string.app_type), "Bearer " + userPrefs.accessToken().get(), 
      new Profile(trimedInvitationMessage, title, 
      String.valueOf(selectedCountry.getCountryCode()), mobilePhone, countryISO, fullName)); 

    call.enqueue(new Callback<Profile>() { 
     @Override 
     public void onResponse(Call<Profile> call, Response<Profile> response) { 
      if (response.body() != null) { 


      } else { 
       if (response.raw().code() == 401) { 
        Call<TokenResponse> refreshTokenCall = trackerService.refreshToken(userPrefs.clientId().get(), 
      userPrefs.clientSecret().get(), "refresh_token", userPrefs.refreshToken().get()); 
        refreshTokenCall.enqueue(new Callback<TokenResponse>() { 
         @Override 
         public void onResponse(Call<TokenResponse> call, Response<TokenResponse> response) { 
          if (response.body() != null) { 

           updateAdviserProfile(trimedInvitationMessage, title, mobilePhone, countryISO, fullName); 
          } else { 
           userPrefs.clear(); 
           Intent intent = new Intent(WelcomeActivity_.launcher(EditProfileActivity.this)); 
           intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
           intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 
           intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 
           intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
           startActivity(intent); 
           startActivity(WelcomeActivity_.launcher(EditProfileActivity.this)); 
          } 
         } 

         @Override 
         public void onFailure(Call<TokenResponse> call, Throwable t) { 

         } 
        }); 
       } else if (response.raw().code() == 422) 
      } 
     } 

     @Override 
     public void onFailure(Call<Profile> call, Throwable t) { 
     } 
    }); 

Odpowiedz

12

Przeszukałem ten temat od 2-3 miesięcy i znalazłem OkHttp 's Authenticator. Możesz tego użyć . Jest jeden link tutaj: refreshing-oauth-token-using-retrofit-without-modifying-all-calls

To działa tak: Jeśli twoja prośba zwróci 401, wtedy przenosi się Authenticator i odświeża swój token. Ale nie zapomnij o return null lub ustaw dowolny limit prób. Jeśli nie ograniczysz, będzie próbował odświeżyć się wiele razy, gdy żądanie odświeżenia nie powiedzie się, a także spowoduje synchroniczne żądania podczas odświeżania tokena.

Również miałem pytanie, być może będzie spojrzeć na to: android-retrofit2-refresh-oauth-2-token

dodatkowo: na przykład, jeśli masz token i trzeba ją odświeżyć za 3 godziny. Możesz również napisać Interceptor. W artykule Interceptor: porównaj czas i odśwież swój token, nie otrzymując żadnej odpowiedzi 401.

Możesz przeczytać Interceptor stronę: OkHttp Interceptors

Można spojrzeć na nie zbyt: OkHttp handling-authentication

wiem, nie ma kodu tutaj, ale spróbuj linki i edytować swoje pytanie, a potem pomogę ci .

+0

PLUS ONE za wyjaśnienie roli OKHttp Authenticator w prostych słowach. To bardzo pomaga – Rinav