首页 文章

Android Retrofit 2.0刷新令牌

提问于
浏览
18

我正在使用 Retrofit 2.0Jackson 转换器与Rest API进行通信 . 某些请求需要授权令牌 . 如果我拥有的令牌已过期,我需要用另一个请求刷新它们并重复上次因此而失败的请求 .

我的问题:我每次都需要手动完成它还是有任何方法可以自动化它?

这是我现在实现它的方式:

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

How I call function and treat it when tokens are out of date

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

1 回答

  • 30

    我在2-3个月前搜索过这个话题,发现 OkHttp 's Authenticator . 你可以使用它 . 这里有一个链接:refreshing-oauth-token-using-retrofit-without-modifying-all-calls

    它的工作方式如下:如果您的请求返回 401 ,则 Authenticator 移入,并刷新您的令牌 . 但不要忘记 return null 或任何尝试限制 . 如果您没有限制,它将在刷新请求失败时尝试刷新多次,并在刷新令牌时进行同步请求 .

    我也有一个问题和答案 - 我自己通过搜索theese链接写的 - 关于刷新Oauth2令牌,也许你会看看它:

    问题:android-retrofit2-refresh-oauth-2-token

    答案:android-retrofit2-refresh-oauth-2-token-answer

    Additionally: 例如,如果您有令牌,则需要每3小时刷新一次 . 你也可以写一个 Interceptor . 在 Interceptor 中:比较时间并刷新令牌而不获取任何 401 响应 .

    你可以阅读 Interceptor 页:OkHttp Interceptors

    你也可以看看那里:OkHttp handling-authentication

    我知道这里没有代码,但尝试链接并编辑您的问题然后我会帮助您 .

相关问题