互联网不稳定时处理访问令牌到期

时间:2018-12-14 01:36:37

标签: android retrofit2 android-authenticator

我将Retrofit2用作Android的HTTP客户端。该应用程序使用访问令牌和刷新令牌与后端进行通信。

场景1:访问令牌已过期,api调用失败,并显示401错误代码,然后我使用Authenticator使用刷新令牌来获取新的一对访问令牌和刷新令牌,并继续使用新的失败呼叫的访问令牌。在稳定的互联网连接下,这一切都很好用

方案2:现在考虑,互联网不稳定,并且不断地掉线。互联网在那里,由于访问令牌过期,api调用失败, 应用程序使用“刷新令牌”进行登录通话,以获取新的一对访问令牌和“刷新令牌”。但是在我获得成功之前,登录电话200掉线了。 现在互联网又回来了,我的应用程序开始再次触发api调用并获得401,然后使用刷新令牌触发新的登录调用。这是问题所在,后端已更新了新的访问和刷新令牌,但由于Internet中断,应用程序从未收到它。由于这个原因,我拥有的刷新令牌不再有效(因为已经在后端创建了一对新令牌并刷新了旧的令牌)

不确定我该如何处理这种情况? 这是我的身份验证器类:

public class MyAuthenticator implements Authenticator {

Context context;

public MyAuthenticator(Context context) {
    this.context = context;
}

@Nullable
@Override
public Request authenticate(Route route, Response response) throws IOException {

    Retrofit client = new Retrofit.Builder()
            .baseUrl(Manager.API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    ApiService service = client.create(ApiService.class);

    SharedPreferenceManager sharedPreferenceManager = new SharedPreferenceManager(context);
    String refreshToken = sharedPreferenceManager.getRefreshToken(context);

    AuthRequest authRequest = new AuthRequest();
    authRequest.grant_type = "refresh_token";
    authRequest.refresh_token = refreshToken;

    Call<authResponse> refreshTokenResult = service.refreshToken(authRequest);
    retrofit2.Response accessTokenResponse = refreshTokenResult.execute();
    //check if response equals 400 , mean empty response
    if (accessTokenResponse.isSuccessful()) {
        AuthResponse refreshResult  = (AuthResponse) accessTokenResponse.body();
        //save new access and refresh token
        sharedPreferenceManager.writeLoginResponse(context, refreshResult);
        // then create a new request and modify it accordingly using the new token
        return response.request().newBuilder()
                .header("Authorization", "Bearer " + refreshResult.access_token)
                .build();

    } else {
        LoginActivity_.intent(context).flags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK).start();
        return null;

    }
}

}

不确定我缺少什么以及如何解决该问题。

1 个答案:

答案 0 :(得分:0)

您不能在客户端执行任何操作。

您要尝试的是一次完全交付新令牌which is impossible。相反,您应该设计一次交货。

您必须为这种情况准备服务器,即它也应该接受旧的刷新令牌,直到它至少接收一次新的访问令牌或刷新令牌。

在此之前,服务器无法确定客户端是否收到新令牌。