无法使用 Retrofit 刷新 Bearer Token

Unable to Refresh Bearer Token using Retrofit

我在我的项目中使用 Retrofit 和 OkHttp,我想在服务器给出 401 错误代码时刷新令牌并将新令牌存储在共享首选项中,然后在不通知用户的情况下再次进行相同的调用。令牌类型为不记名,每小时过期。

但是我想要的输出没有出现,当令牌过期时,身份验证器什么都不做。

ApiInterface.java

public interface ApiInterface {
    @FormUrlEncoded
    @POST("auth/login")
    Call<ResponseBody> login(@FieldMap HashMap<String, Object> map);

    @FormUrlEncoded
    @POST("auth/register")
    Call<ResponseBody> register(@FieldMap HashMap<String, Object> map);

    @FormUrlEncoded
    @POST("auth/forgotpassword")
    Call<ResponseBody> forgotPassword(@FieldMap HashMap<String, Object> map);

    @POST("auth/refresh")
    Call<ResponseBody> refreshToken(@Header("Authorization") String token);

    @POST("auth/GetAllInterests")
    Call<ResponseBody> getAllInterest();

    @POST("auth/AddUserProfile")
    @Multipart
    Call<ResponseBody> addUserProfile(
            @Part("display_name") RequestBody display_name,
            @Part("children_age_show") RequestBody children_age_show,
            @Part("address") RequestBody address,
            @Part("no_of_children") RequestBody no_of_children,
            @Part("children_age") RequestBody children_age,
            @Part("date_of_birth") RequestBody date_of_birth,
            @Part("interests") RequestBody interests,
            @Part List<MultipartBody.Part> images
    );

    @POST("auth/GetUserProfile")
    Call<ResponseBody> getUserProfile();

    @FormUrlEncoded
    @POST("auth/ChangePassword")
    Call<ResponseBody> changePassword(@FieldMap HashMap<String, Object> map);

    @POST("auth/logout")
    Call<ResponseBody> logout();
}

ApiClient.java

public class ApiClient {
    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface = null;

    public static Retrofit getRetrofit(Context context) {
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();

                        if (AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN) != null) {
                            request = request.newBuilder()
                                    .addHeader("Authorization", AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
                                    .build();
                        }

                        return chain.proceed(request);
                    }
                })
                .authenticator(new TokenAuthenticator(context))
                .build();

        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(Constants.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }

    public static ApiInterface getApiInterface(Context context) {
        if (apiInterface == null) {
            getRetrofit(context);
            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }
}

TokenAuthenticator.java
public class TokenAuthenticator implements Authenticator {
    Context context;

    public TokenAuthenticator(Context context) {
        this.context = context;
    }

    @Override
    public Request authenticate(Route route, Response response) throws IOException {
        Log.d("Authenticator", "Authenticator Called");
        if (response.code() == 401) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Constants.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            Log.d("Authenticator", "Requesting for New Token");
            ApiInterface apiInterface = retrofit.create(ApiInterface.class);

            retrofit2.Response<ResponseBody> response1 = apiInterface
                    .refreshToken(AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
                    .execute();

            if (response1.isSuccessful()) {
                try {
                    String body = response1.body().string();
                    JSONObject jsonObject = new JSONObject(body);

                    if (jsonObject.getBoolean("status")) {
                        String newToken = "Bearer " + jsonObject.getJSONObject("Data").getString("access_token");
                        AppPreference.setPreference(context, AppPersistence.keys.AUTH_TOKEN, newToken);

                        Log.d("Authenticator", "New Token Generated");
                        return response.request().newBuilder()
                                .header("Authorization", newToken)
                                .build();
                    }
                } catch (Exception e) {
                    Log.e("TokenAuthenticator", e.getMessage(), e);
                }
            }

            Toast.makeText(context, response1.body().string(), Toast.LENGTH_SHORT).show();
        }

        return null;
    }
}

请尝试以下方式

 (1)   HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    
                try {
                    httpClient.addInterceptor(new Interceptor() {
                        @Override
                        public Response intercept(Interceptor.Chain chain) throws IOException {
                            Request request = chain.request();
                            // try the request
                            Response response = chain.proceed(request);
                            if (response shows expired token) {
                                // get a new token (I use a synchronous Retrofit call)
                                // create a new request and modify it accordingly using the new token
                                Request newRequest = request.newBuilder().build();
    
                                // retry the request
                                return chain.proceed(newRequest);
                            }
                            // otherwise just pass the original response on
                            return response;
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
                String baseUrl = "";
                Retrofit retrofit = new Retrofit.Builder()
                        .client(okHttpClient)
                        .baseUrl(baseUrl)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
                apiService = retrofit.create(ApiService.class);


(2)  public class TokenAuthenticator implements Authenticator {

        private final ApiService apiservice;

        public TokenAuthenticator(TokenServiceHolder tokenServiceHolder) {
            this.tokenServiceHolder = tokenServiceHolder;
        }

        @Override
        public Request authenticate(Proxy proxy, Response response) throws IOException {
            newtoken = apiservice.refreshToken().execute();
            return response.request().newBuilder()
                    .header(AUTHORIZATIONKEY, newtoken)
                    .build();
        }

        @Override
        public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
            // Null indicates no attempt to authenticate.
            return null;
        }
    }

希望对您有所帮助