工作生活

Retrofit中Token过期处理

2019-06-29  本文已影响0人  烂吹笙

Android中使用Retrofit刷新Token

实际开发中,例如登录,我们向后台传参用户名和密码,后台会返回给我们一个Token,用于后面接口的调用,
这样后端就能通过我们传入的token知道我们是哪个用户,一般token的有效期是2小时。2小时候token会自动过期。我们需要拿到新的Token,保持登陆状态。

如何刷新Token呢

刷新Token流程图.png

如上图所示,我们loging过后后台返回token、refreshToken给客户端,token有效时长2小时,而refreshToken时间较长有15天,2小时候我们调用接口,后端告诉我们token过期,那我们拿之前存的refreshToken去调用刷新Token的接口,后端会从新给我一个新的token和refreshToken,依次类推,我们就能实现长期登录,除非用户15天不登录,refreshToken过期。


public class TokenInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request originalRequest = chain.request();
        Response response = chain.proceed(originalRequest);

        try {
            ResponseBody responseBody = response.body();
            //解决response.body().string();只能打印一次
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
            Charset UTF8 = Charset.forName("UTF-8");
            String string = buffer.clone().readString(UTF8);

            BaseResponseBean baseResponseBean = new Gson().fromJson(string, BaseResponseBean.class);
            if (baseResponseBean != null) {
                if (baseResponseBean.getCode().equals(ResponseCode.TOKEN_ERROR)) {
                    //token过期
                    //根据RefreshToken同步请求,获取最新的Token
                    String newToken = getNewToken();

                    //使用新的Token,创建新的请求
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("authToken", newToken)
                            .build();
                    //重新请求
                    return chain.proceed(newRequest);
                } else if (baseResponseBean.getCode().equals(ResponseCode.REFRESH_TOKEN_ERROR)) {
                    //refreshToken过期
                    EventBus.getDefault().post(new Handler(Looper.getMainLooper()).obtainMessage(Constants
                            .Key_EventBus_Msg.EVENT_TOKEN_OVERDUE));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }


    /**
     * 同步请求方式,根据RefreshToken获取最新的Token
     *
     * @return
     */
    private synchronized String getNewToken() throws IOException {
//        通过一个特定的接口获取新的token,此处要用到同步的retrofit请求
        String newToken = "";
        String paramsRefresh = "";

        TokenInfoBean oldTokenBean = TokenInfoBean.readToken();
        if (oldTokenBean != null && !BaseUtils.isEmpty(oldTokenBean.getRefreshToken())) {
            paramsRefresh = oldTokenBean.getRefreshToken();
        }

        ApiService apiService = ApiRetrofit.create(ApiService.class);
        RequestBody requestBody = RequestBody.create(MediaType.parse(ContentTypeConstant.Content_TYPE_JSON), "");
        Call<BaseResponseBean<TokenInfoBean>> call = apiService.refreshToken(paramsRefresh, requestBody);
        BaseResponseBean<TokenInfoBean> responseBean = call.execute().body();
        if (responseBean != null && responseBean.getCode().equals(ResponseCode.RESPONSE_SUCCES)
                && responseBean.getData() != null && !BaseUtils.isEmpty(responseBean.getData().getToken())) {
            //获取新的token成功
            TokenInfoBean infoBean = responseBean.getData();
            TokenInfoBean.saveToken(infoBean);
            newToken = infoBean.getToken();
        }
        return newToken;
    }
}

上一篇下一篇

猜你喜欢

热点阅读