为什么不调用改造 Authenticator?

Nic*_*hek 3 java authentication android retrofit retrofit2

我想将响应从服务器更改为 423 -> 401,然后使用 Authenticator 调用 refreshToken。

如果响应代码为 401,则调用该方法

但是为什么 在我的情况下不调用该方法Authenticator.authenticate(Route route, Response response)

OkHttp客户端

OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    //Adding token to request
                    Request request = chain.request();
                    Request.Builder builder = request.newBuilder();
                    builder.header("Authorization", "access_token");
                    return chain.proceed(builder.build());
                }
            })
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    //changing response code from server 423 -> 401
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    if (response.code() == 423)
                        return response.newBuilder().code(401).build();
                    return response;
                }
            })
            .authenticator(new Authenticator() {
                //THE METHOD IS NOT CALLED, WHY?
                @Override
                public Request authenticate(Route route, Response response) throws IOException {
                    // Refresh access_token using a synchronous api request
                    String newAccessToken = refreshToken();
                    saveNewToken(newAccessToken)
                    // Add new header to rejected request and retry it
                    return response.request().newBuilder()
                            .header("Authorization", newAccessToken)
                            .build();
                }
            })
            .build();
Run Code Online (Sandbox Code Playgroud)

改造界面:

 ApiService mApiService = new Retrofit.Builder()
                        .baseUrl(serverHostUrl)
                        .client(httpClient)
                        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        .build()
                        .create(ApiService.class);
Run Code Online (Sandbox Code Playgroud)

Fre*_*red 7

我觉得这里的问题是,之间的差异application interceptorsnetwork interceptors。你可以在这里阅读所有关于它的内容并且应该这样做,因为有很多不同之处。

就您而言,简而言之,我认为您是在OkHttp检查状态代码并尝试运行身份验证器后更改响应代码。因此,解决方案是使用网络拦截器而不是像您现在拥有的应用程序拦截器来更改状态代码。

如果您查看getResponseWithInterceptorChain 方法RealCall.java您会发现拦截器堆栈是通过首先添加所有应用程序拦截器,然后添加一些内部拦截器,最后添加网络拦截器来构建的。您会看到内部拦截器之一是RetryAndFollowUpInterceptor,它似乎在这里处理身份验证器代码。

所以似乎正在发生的是你提出你的请求。更改代码的拦截器在链上运行并调用继续。请求会通过所有剩余的拦截器,但让我们关注RetryAndFollowUpInterceptor. 这个将在您之后运行并在链中继续。它得到响应并有一个带有代码的响应,423并且不会做任何重新验证的事情。然后它会返回,现在你的拦截器正在运行。它看到一个响应代码423并更改它,但这不会RetryAndFollowUpInterceptor再次运行。

如您所见,您似乎在应用程序中更改代码太晚或太高。您必须确保在RetryAndFollowUpInterceptor有机会查看响应代码之前这样做,并且使用网络拦截器更容易做到这一点。除了简单的状态代码之外,您还需要处理更多的事情,但这是可能的。

希望这可以帮助