2016-06-11 45 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