草庐IT

Android Retrofit 2.0 刷新 token

coder 2023-06-08 原文

我正在使用带有 Jackson 转换器的 Retrofit 2.0 与 Rest API 进行通信。一些请求需要授权 token 。如果我拥有的 token 已过期,我需要用另一个请求刷新它们并重复上一个因此而失败的请求。

我的问题:我需要每次都手动完成还是有什么方法可以自动完成?

这是我目前实现它的方式:

TrackerService

public interface TrackerService {

    @POST("auth/sendPassword")
    Call<ResponseMessage> sendPassword(@Header("app-type") String appType, 
                                       @Body User userMobile);

    @FormUrlEncoded
    @POST("oauth/token")
    Call<TokenResponse> oathToken(@Field("client_id") String clientId,
                                  @Field("client_secret") String clientSecret,
                                  @Field("grant_type") String grantType,
                                  @Field("username") String username,
                                  @Field("password") String password);

    @FormUrlEncoded
    @POST("oauth/token")
    Call<TokenResponse> refreshToken(@Field("client_id") String clientId,
                                     @Field("client_secret") String clientSecret,
                                     @Field("grant_type") String grantType,
                                     @Field("refresh_token") String username);


    @PUT("me/profile")
    Call<Profile> updateProfile(@Header("app-type") String appType,
                                @Header("Authorization") String token,
                                @Body Profile profile);

}

服务网关

public class ServiceGateway {

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    private static Retrofit retrofit;

    public static <S> S createService(Class<S> serviceClass) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(20 * 1000, TimeUnit.MILLISECONDS)
                .writeTimeout(20 * 1000, TimeUnit.MILLISECONDS)
                .readTimeout(20 * 1000, TimeUnit.MILLISECONDS)
                .addInterceptor(interceptor).build();

        Retrofit.Builder builder =
                new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(JacksonConverterFactory.create());

        retrofit = builder.client(httpClient.build())
                .client(client)
                .build();
        return retrofit.create(serviceClass);
    }

    public static Retrofit getRetrofit() {
        return retrofit;
    }
}

token 过期时如何调用函数和处理函数

 trackerService = ServiceGateway.createService(TrackerService.class);

    Call<Profile> call = trackerService.updateProfile(getString(R.string.app_type), "Bearer " + userPrefs.accessToken().get(),
            new Profile(trimedInvitationMessage, title,
            String.valueOf(selectedCountry.getCountryCode()), mobilePhone, countryISO, fullName));

    call.enqueue(new Callback<Profile>() {
        @Override
        public void onResponse(Call<Profile> call, Response<Profile> response) {
            if (response.body() != null) {


            } else {
                if (response.raw().code() == 401) {
                    Call<TokenResponse> refreshTokenCall = trackerService.refreshToken(userPrefs.clientId().get(),
            userPrefs.clientSecret().get(), "refresh_token", userPrefs.refreshToken().get());
                    refreshTokenCall.enqueue(new Callback<TokenResponse>() {
                        @Override
                        public void onResponse(Call<TokenResponse> call, Response<TokenResponse> response) {
                            if (response.body() != null) {

                                updateAdviserProfile(trimedInvitationMessage, title, mobilePhone, countryISO, fullName);
                            } else {
                                userPrefs.clear();
                                Intent intent = new Intent(WelcomeActivity_.launcher(EditProfileActivity.this));
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                                startActivity(WelcomeActivity_.launcher(EditProfileActivity.this));
                            }
                        }

                        @Override
                        public void onFailure(Call<TokenResponse> call, Throwable t) {

                        }
                    });
                } else if (response.raw().code() == 422)
            }
        }

        @Override
        public void onFailure(Call<Profile> call, Throwable t) {
        }
    });

最佳答案

我从2-3个月前开始搜索这个主题,发现OkHttp's Authenticator。你可以使用它。这里有一个链接:refreshing-oauth-token-using-retrofit-without-modifying-all-calls

它的工作原理是这样的:如果您的请求返回 401,那么 Authenticator 会进入并刷新您的 token 。但不要忘记 return null 或设置任何尝试限制。如果你不限制,它会在你的刷新请求失败时尝试多次刷新。此外,刷新 token 时发出同步请求。

另外,我有一个关于刷新 Oauth2 token 的问答(均由我自己编写):

问题:android-retrofit2-refresh-oauth-2-token

答案:android-retrofit2-refresh-oauth-2-token-answer

另外:例如,如果您有一个 token 并且您需要每 3 小时刷新一次。你也可以写一个Interceptor。在 Interceptor 中:比较时间并刷新您的 token ,而不会收到任何 401 响应。

Interceptor 的 Square 文档:OkHttp Interceptors

Square 的 Authenticator 文档:OkHttp handling-authentication

我知道这里没有代码,但请查看链接并编辑您的问题,然后我会尽力帮助您。

关于Android Retrofit 2.0 刷新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37764670/

有关Android Retrofit 2.0 刷新 token的更多相关文章

  1. 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

  2. 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来发送

  3. 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

  4. 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

  5. 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

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

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

  7. ruby-on-rails - 如何在 ruby​​ on rails 中为 gmail 联系人创建访问 token - 2

    我正在使用Omniauth请求用户gmail凭据,因此我可以稍后请求用户friend/联系人。现在,我正在使用身份验证请求为我生成的访问token,在OmniauthCallbacksController中获取好友列表。像这样classUsers::OmniauthCallbacksController如何使用存储在数据库中的凭据创建新的访问token,以便从不同的Controller调用googleAPI? 最佳答案 从here获取您的client_id和client_secret|.这是一个粗略的脚本,可以很好地工作。根据您的需

  8. ruby-on-rails - Rails 4 真实性 token - 在 header 和表单隐藏输入中? - 2

    我正试图在Rails中获得完整的页面缓存,但我在CSRF方面遇到了很大的障碍——或者可能只是我对它的理解。我目前有form_authenticity_token存储在cookie中的字符串,JS可以使用该cookie访问和重写header标签。我在生成的HTML中有两个地方可以找到标记:1)在头部2)在表单的隐藏输入元素中如前所述,这些哈希值彼此不同(在未启用缓存的开发模式下)。他们为什么不同?为什么我可以删除headmeta标签并保留表单输入并且允许请求​​?然而,当我删除表单输入标签并保留标题时,请求被拒绝了吗?实际上这意味着head标签是无用的,不是吗?我可以将表单输入标签重写为

  9. ruby-on-rails - 如何访问设计 token 授权注册 Controller ? - 2

    我正在使用Deviseauthtokengem用于验证我的Rails应用程序的某些部分。但是,当我尝试使用注册路径创建新用户时,出现以下错误{"errors":["Authorizedusersonly."]}。这是我用于测试的rspec代码,it'createsauserusingemail/passwordcombo'dopostapi_user_registration_path,{email:'xxx',password:'yyy',password_confirmation:'yyy'}putslast_response.bodyexpect(last_response.bo

  10. ruby - Stripe 访问 token 和 API SK key 有什么区别? - 2

    StripeAPI引用关于authentication的描述:他们给出的例子是这样的:require"stripe"Stripe.api_key="sk_test_BQokikJOvBiI2HlWgH4olfQ2"sk_test_BQokikJOvBiI2HlWgH4olfQ2key可在Stripe网页的帐户设置中找到。我知道这是我的应用程序与Stripe对话的secretAPIkey。但后来我在gettingstartedwithStripeConnect上阅读了这份文档:WhenusingourofficialAPIlibraries,werecommendthatyoupassi

随机推荐