2016-06-11 68 views
7

我正在使用Retrofit 2.0Jackson轉換器與Rest API進行通信。部分請求需要授權令牌。如果我擁有的令牌已經過期,我需要用另一個請求刷新它們,並重覆上次因此而失敗的請求。Android Retrofit 2.0刷新標記

我的問題:我是否需要手動每次都做,或者有什麼方法可以自動化嗎?

這裏就是這樣,我在那一刻實現它:

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; 
    } 
} 

我如何調用函數,把它當令牌過時

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) { 
     } 
    }); 

回答

12

我在2-3個月前搜索了這個話題,發現OkHttp 's Authenticator。你可以使用它。這裏有一個鏈接:refreshing-oauth-token-using-retrofit-without-modifying-all-calls

它的工作原理是這樣的:如果您的請求返回401,那麼Authenticator會移入並刷新您的令牌。但不要忘記return null或放任何嘗試限制。如果您沒有限制,刷新請求失敗時它會嘗試刷新多次,並且在刷新令牌時也會發出同步請求。

我也有一個問題,也許你會看看它:android-retrofit2-refresh-oauth-2-token

另外:例如,如果你有一個令牌,你需要刷新每3小時。你也可以寫一個Interceptor。在Interceptor:比較時間並刷新您的令牌,但未收到任何401響應。

您可以閱讀Interceptor頁:OkHttp Interceptors

你可以看看有太多:OkHttp handling-authentication

我知道有沒有代碼在這裏,但嘗試鏈接和編輯你的問題,然後我會幫你。

+0

PLUS ONE用於解釋OKHttp Authenticator在簡單單詞中的角色。這有很大幫助 – Rinav