You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit调用始终使用旧Token导致401未授权,如何解决?

问题分析与解决方案

核心问题

  1. Retrofit单例复用旧Interceptor:你的RetrofitClient采用单例模式,仅在首次调用时初始化Retrofit实例,Interceptor中捕获的auth变量是首次传入的旧Token,后续即使传入新Token,也不会重新创建Interceptor,导致所有请求仍使用旧Token。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:50:44