草庐IT

android - OkHttp 和 Retrofit,并发请求刷新 token

coder 2023-11-27 原文

在我的应用程序中,我实现了 Retrofit 来调用 WebServices,并且我使用 OkHttp 来使用拦截器和验证器。有些请求需要 token ,我已经实现了 Authenticator 接口(interface)来处理刷新(遵循官方 documentation )。但我有以下问题:在我的应用程序中,有时我必须一次调用多个请求。因此,对于其中一个,我将遇到 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;
    }

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

谢谢!

最佳答案

如果我理解你的问题,在更新 token 时发送了一些请求,这会给你一个错误。

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

由于这个问题很难完全避免,也许这里正确的做法是有一个良好的回退行为。例如,通过使用更新后的 token 重新运行请求来处理在 token 更新期间发出请求时遇到的错误。

关于android - OkHttp 和 Retrofit,并发请求刷新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44386722/

有关android - OkHttp 和 Retrofit,并发请求刷新 token的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

    似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

  3. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  4. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  5. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

  6. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  7. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

  8. ruby-on-rails - 设计通过 reset_password_token 获取用户 - 2

    我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow

  9. ruby - token 认证 - 2

    简单代码require'net/http'url=URI.parse('getjson/otherdatahere[link]')req=Net::HTTP::Get.new(url.to_s)res=Net::HTTP.start(url.host,url.port){|http|http.request(req)}putsres.body只是想知道如何在phpcURL中放置身份验证token,我是这样做的    curl_setopt($ch,CURLOPT_HTTPHEADER,array('Authorization:Bearerxxx'));//Bearertokenfora

  10. ruby-on-rails - 访问授权和访问 token 之间的区别 - 2

    Doorkeeper中Token和Grant的区别我搞不清楚。Doorkeeper在哪个时刻创建访问授权,何时创建访问token?文档似乎对此什么也没说,现在我正在阅读代码,但不是十几行。 最佳答案 我还建议阅读documentationofoauth2据我了解,Doorkeeper也是基于该文档中描述的协议(protocol)。在doorkeeper中,你会先获得accessgrant,然后是accesstoken。访问授权通常只存在很短的时间(doorkeeper中的默认值为10分钟)。您将通过向api-url/oauth/au

随机推荐