我有一个改造客户端,可以帮助我为我对 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/