为什么没有调用改造身份验证器?

时间:2018-01-26 09:59:37

标签: java android authentication retrofit retrofit2

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

The method is called if response code is 401

但为什么在我的案例中没有调用 Authenticator.authenticate(Route route, Response response) 的方法?

OkHttpClient

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

改造界面:

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

1 个答案:

答案 0 :(得分:1)

我认为这里的问题是application interceptorsnetwork interceptors之间的区别。您可以阅读所有相关内容here,并且应该这样做,因为存在很多差异。

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

如果从RealCall.java查看method getResponseWithInterceptorChain,您会看到拦截器堆栈是通过首先添加所有应用程序拦截器然后是一些内部拦截器然后最后添加网络拦截器来构建的。您会看到其中一个内部拦截器是RetryAndFollowUpInterceptor,它似乎处理验证码here

所以似乎正在发生的是你提出要求。用于更改代码的拦截器运行并在链上进行调用。请求通过所有剩余的拦截器,但让我们关注RetryAndFollowUpInterceptor。这个将在你的后面运行并继续在链中。它获得响应并且具有代码423的响应,并且不会执行任何重新进行身份验证的操作。它将返回,现在它是你的拦截器运行。它会看到响应代码423并对其进行更改,但这不会再次运行RetryAndFollowUpInterceptor

如您所见,您似乎在应用程序中将代码更改为太晚或太高。在RetryAndFollowUpInterceptor有机会查看响应代码之前,您必须确保执行此操作,并且使用网络拦截器可以更轻松地完成此操作。除了简单的状态代码之外,你还需要处理更多的事情,但这是可能的。

希望这有帮助