改造无法将新令牌设置为请求的 Header

Retrofit unable to set new Token to Header of Requests

我有一个改装客户端,可以帮助我为我对 REST API 发出的任何请求设置 header。在用户登录时,我从服务器获取令牌并将此令牌设置为请求的 header。我将此令牌保存到 SharedPreferences,以便我可以在需要向我的 REST API 发出请求时随时获取它。问题是,每当我在新用户登录时为我的 SharedPreferences 文件设置一个新令牌时,它仍然会获得旧令牌,而不是保存这个新令牌以用于将来的请求。

下面是我的 Retrofit 客户端:

public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient(String token) {

        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okClient = new OkHttpClient();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        okClient.interceptors().add(chain -> chain.proceed(chain.request()));

        okClient.interceptors().add(chain -> {
            Request original = chain.request();
            Request request = original.newBuilder()
                    .header(Config.X_AUTH_TOKEN, "Bearer" + " " + token)
                    .method(original.method(), original.body())
                    .build();
            Log.d("Authorization", token);

            return chain.proceed(request);
        });

        okClient.interceptors().add(logging);

        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(Config.BASE_URL1)
                    .client(okClient)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }
        return retrofit;
    }

}

这是我设置和获取令牌的代码

public String getToken() {
    return prefs.getString(AuthUser.USER_TOKEN, "");
}

public void setToken(String token) {
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString(AuthUser.USER_TOKEN, token);
    editor.apply();
}

这是我调用设置令牌方法将新令牌保存到 SharedPreference 的地方

 authUser.setToken(token);

我完全不明白这有什么好惊讶的。您的 RetrofitClient 是一个令人困惑(并且可以说写得很糟糕)的单身人士。让我们来看一个失败的典型情况。

您使用之前保存的令牌启动您的应用程序。起初一切正常。在某个时候,您调用 RetrofitClient.getClient(token) 并且所有请求都成功。一段时间后,服务器使令牌无效。您可能会从您的服务器收到 403 响应,再次启动登录屏幕并在您的 SharedPreferences 中更新您的令牌。这是您的问题开始的地方。尽管您正确保存了新令牌,但您的 RetrofitClient 将执行单身人士所做的事情并继续 return 存储在 private static Retrofit retrofit 文件中的自身的第一个实例化。

一个快速的解决方法是向您的 RetrofitClient 添加一个无效方法。有点像。

public static void invalidate() {
  this.retrofit = null;
}

在收到 403 响应或注销时调用它。

PS:请将以下行 if (retrofit==null) { 移到 getClient 方法的开头。创建一个新的 okHttp 客户端,没有任何意义,每次有人调用 getClient 都是浪费。

你可以编写拦截器在每次网络请求之前执行happen.Create new file as HeaderIntercepter

public class HeaderIntercepter implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    String token = context.getSharedPreferences(FILENAME, MODE_PRIVATE).getString("TOKEN","");

    Request tokenRequest = request.newBuilder()
            .addHeader("Authorization", "Bearer " + token)
            .addHeader("Content-Type", "application/json")
            .build();

    return chain
            .proceed(tokenRequest);
}
}

为okHttpclient添加拦截器

 OkHttpClient.Builder builder = new OkHttpClient.Builder()
            .addInterceptor(new HeaderIntercepter());