java - 改造无法将新 token 设置为请求 header

标签 java android sharedpreferences retrofit2 request-headers

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

下面是我的 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;
    }

}

这是我设置和获取 token 的代码

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

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

 authUser.setToken(token);

最佳答案

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

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

一个快速的解决方法是向您的 RetrofitClient 添加一个无效方法。类似的东西。

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

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

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

关于java - 改造无法将新 token 设置为请求 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48357749/

相关文章:

android:从字符串数组中获取项目并在 TextView 中一一显示

java - String 是 Android 或 Java 中的原语还是对象?

java - 对文件进行 md5 处理,而不读取内存中的完整文件

java - Spring Tool Suite (STS) 3.5.0 - org.codehaus.groovy.eclipse 在求解器中未知

android - 在 Android 中使 ListPreference 多项选择的简单方法?

android - Flutter 在现有项目中

android - 应用程序崩溃,出现错误 : The String#value field is not present on Android versions >= 6. 0

java - Android HashSet 无法转换为 LinkedHashSet

java - 如何更新 jar 文件中的参数?

java - 如何将不同模块中的类捆绑到 jar 中?