Retrofit调用始终使用旧Token导致401未授权,如何解决?
问题分析与解决方案
核心问题
- Retrofit单例复用旧Interceptor:你的
RetrofitClient采用单例模式,仅在首次调用时初始化Retrofit实例,Interceptor中捕获的auth变量是首次传入的旧Token,后续即使传入新Token,也不会重新创建Interceptor,导致所有请求仍使用旧Token。 - OkHttp连接池复用旧连接:OkHttp会复用同一地址的连接,旧连接携带的Authorization头是旧Token,即使更新了Header,复用旧连接时仍会使用旧值。
解决方案
方案1:动态获取Token(推荐)
修改Interceptor逻辑,让每次请求时实时从数据库/全局缓存获取最新Token,而非初始化时固定值。同时用header()替换addHeader(),确保覆盖旧的Authorization头,避免重复添加。
修改后的RetrofitClient代码:
public class RetrofitClient { private static Retrofit retrofit = null; // 实现从数据库读取最新Token的方法 private static String getLatestToken() { // 替换为你的数据库查询逻辑(如Room、SharedPreferences) return YourDBUtil.getLatestEBayToken(); } public static Retrofit getClient(String baseUrl) { if (retrofit == null) { OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); okHttpClient.addInterceptor(chain -> { // 每次请求动态获取最新Token String authHeader = "Bearer " + getLatestToken(); Request newRequest = chain.request().newBuilder() .header("Authorization", authHeader) // 覆盖旧Header .header("Content-Type", "application/json") .build(); return chain.proceed(newRequest); }); retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient.build()) .build(); } return retrofit; } // Token更新后调用此方法,清空连接池避免复用旧连接 public static void invalidateConnections() { if (retrofit != null) { retrofit.client().connectionPool().evictAll(); } } }
使用方式:
- 初始化Retrofit时仅传入
baseUrl,无需传入Token; - 当Token过期并更新到数据库后,调用
RetrofitClient.invalidateConnections()清空连接池,强制后续请求创建新连接。
方案2:重建Retrofit实例
放弃单例的复用逻辑,每次获取新Token时重新创建Retrofit和OkHttpClient实例,确保使用最新的Token初始化Interceptor。
代码示例:
public class RetrofitClient { public static Retrofit getClient(String baseUrl, String token) { String authHeader = "Bearer " + token; OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); okHttpClient.addInterceptor(chain -> { Request newRequest = chain.request().newBuilder() .header("Authorization", authHeader) .header("Content-Type", "application/json") .build(); return chain.proceed(newRequest); }); return new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient.build()) .build(); } }
使用方式:每次Token更新后,调用getClient()传入新Token,获取新的Retrofit实例用于后续请求。
关键注意点
- 避免使用
addHeader(),因为它会在原有Header基础上追加,可能导致同一个请求携带多个Authorization头,引发服务端验证错误; - 清空连接池是解决OkHttp复用旧连接的关键,否则即使Token更新,旧连接仍会携带旧Header发起请求。
内容的提问来源于stack exchange,提问作者Michael Blaser
相关产品推荐
相关产品推荐

