java - 为什么不调用改造 validator ?

标签 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);

最佳答案

我认为这里的问题是应用程序拦截器网络拦截器之间的区别。您可以阅读所有相关内容here并且应该这样做,因为存在相当大的差异。

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

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

看来正在发生的事情是你提出了你的要求。改变代码的拦截器在链上运行并调用。该请求将遍历所有剩余的拦截器,但让我们重点关注 RetryAndFollowUpInterceptor。这个将追随你的并在链条中继续前进。它收到响应并收到代码为 423 的响应,并且不会执行任何重新身份验证操作。然后它会返回,现在你的拦截器正在运行。它看到响应代码 423 并更改它,但这不会再次运行 RetryAndFollowUpInterceptor

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

希望这有帮助

关于java - 为什么不调用改造 validator ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48459111/

相关文章:

java - 如何将多个参数传递给 Saxon ExtensionFunction?

android - 使用 sqlite 数据库在 Android 中完成登录和注册?

java - 过滤器映射在 web.xml 中不起作用

android - 一旦所有 EditText 字段不为空,启用按钮

android - 将字符串从服务传递到 Intent

node.js - NodeJS 访问 token 与刷新 token

python - HTTP 错误 401 : Authorization Required while downloading a file from HTTPS website and saving it

java - 无法将 Jasypt 加密密码保存到 .properties 文件

Java-程序不显示输出

java - 是否存在 if 语句无法被跳转表替代的情况?