OkHttp 和 Retrofit,并发请求刷新 token

2024-04-18

在我的应用程序中,我实现了 Retrofit 来调用 WebServices,并使用 OkHttp 来使用拦截器和身份验证器。有些请求需要token https://jwt.io/,并且我已经实现了 Authenticator 接口来处理刷新(遵循官方文档 https://github.com/square/okhttp/wiki/Recipes#handling-authentication)。但我有以下问题:在我的应用程序中,我有时必须一次调用多个请求。因此,对于其中一个我将出现 401 错误。

这是我的请求调用代码:

public static <S> S createServiceAuthentication(Class<S> serviceClass, boolean hasPagination) {

        final String jwt = JWT.getJWTValue(); //Get jwt value from Realm

        if (hasPagination) {
            Gson gson = new GsonBuilder().
                    registerTypeAdapter(Pagination.class, new PaginationTypeAdapter()).create();

            builder =
                    new Retrofit.Builder()
                            .baseUrl(APIConstant.API_URL)
                            .addConverterFactory(GsonConverterFactory.create(gson));
        }

        OkHttpClient.Builder httpClient =
                new OkHttpClient.Builder();

        httpClient.addInterceptor(new AuthenticationInterceptor(jwt));
        httpClient.authenticator(new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                if (responseCount(response) >= 2) {
                    // If both the original call and the call with refreshed token failed,
                    // it will probably keep failing, so don't try again.
                    return null;
                }

                if (jwt.equals(response.request().header("Authorization"))) {
                    return null; // If we already failed with these credentials, don't retry.
                }

                APIRest apiRest = createService(APIRest.class, false);
                Call<JWTResponse> call = apiRest.refreshToken(new JWTBody(jwt));
                try {
                    retrofit2.Response<JWTResponse> refreshTokenResponse = call.execute();
                    if (refreshTokenResponse.isSuccessful()) {

                        JWT.storeJwt(refreshTokenResponse.body().getJwt());

                        return response.request().newBuilder()
                                .header(CONTENT_TYPE, APPLICATION_JSON)
                                .header(ACCEPT, APPLICATION)
                                .header(AUTHORIZATION, "Bearer " + refreshTokenResponse.body().getJwt())
                                .build();
                    } else {
                        return null;
                    }
                } catch (IOException e) {
                    return null;
                }
            }
        });

        builder.client(httpClient.build());
        retrofit = builder.build();

        return retrofit.create(serviceClass);
    }

    private static int responseCount(Response response) {
        int result = 1;
        while ((response = response.priorResponse()) != null) {
            result++;
        }
        return result;
    }

问题很简单,第一个请求将成功刷新令牌,但其他请求将失败,因为它们将尝试刷新已经刷新的令牌。 WebService 返回错误 500。是否有任何优雅的解决方案可以避免这种情况?

谢谢 !


如果我理解您的问题,则在更新令牌时会发送一些请求,这会给您带来错误。

您可以尝试在更新令牌(使用“同步”对象)时阻止所有请求,但这不会涵盖已发送请求的情况。

由于这个问题很难完全避免,也许正确的方法是拥有良好的后备行为。例如,通过使用更新的令牌重新运行请求来处理令牌更新期间发出请求时出现的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OkHttp 和 Retrofit,并发请求刷新 token 的相关文章

随机推荐