Android Token过期解决方案

对开发中遇到的问题进行整理记录~~


场景:Token验证较多的Android应用;


需求:在Token过期后,向服务器重新获取Token并使用新Token重新发起请求;


实现: 参考:http://www.jianshu.com/p/62ab11ddacc8

1、服务器若能在Token过期时返回401错误码,则可以使用OkHttp提供的Authenticator接口(未验证);

2、实现OkHttp的Interceptor接口,并使用同步的Retrofit请求


public class TokenInterceptor implements Interceptor {
    @ParametersAreNonnullByDefault
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response originalResponse = chain.proceed(request);

        String url = request.url().toString();//请求Url

        //获取返回的json,response.body().string();只有效一次,对返回数据进行转换
        ResponseBody responseBody = originalResponse.body();
        BufferedSource source = responseBody.source();
        source.request(Long.MAX_VALUE); // Buffer the entire body.
        Buffer buffer = source.buffer();
        Charset charset = Charset.forName("UTF-8");
        MediaType contentType = responseBody.contentType();
        if (contentType != null) {
            charset = contentType.charset(Charset.forName("UTF-8"));
        }
        String bodyString = buffer.clone().readString(charset);//首次请求返回的结果

        if (isTokenExpired(bodyString)) {//根据和服务端的约定判断token过期
            //同步请求方式,获取最新的Token
            TokenEntity tokenEntity = getNewToken();
            //使用新的Token,创建新的请求
            if(request.body() instanceof FormBody){
                FormBody.Builder newFormBody = new FormBody.Builder();
                FormBody oidFormBody = (FormBody) request.body();
                for (int i = 0;i<oidFormBody.size();i++){
                    //根据需求修改参数
                    if ("需要更新的token参数字段".equals(oidFormBody.encodedName(i))) {
                        newFormBody.addEncoded(oidFormBody.encodedName(i),tokenEntity.getToken());
                    }else {
                        newFormBody.addEncoded(oidFormBody.encodedName(i),oidFormBody.encodedValue(i));
                    }
                }
                Request.Builder builder = request.newBuilder();
                builder.url(url);
                builder.method(request.method(),newFormBody.build());
                request = builder.build();
            }
            originalResponse.body().close();
            //重新请求
            return chain.proceed(request);
        }
        return originalResponse;
    }

    /**
     * 根据Response约定,判断Token是否失效
     * @param response
     */
    private boolean isTokenExpired(String response) {
        JSONObject obj = null;
        try {
            obj = new JSONObject(response);
            if ("Token过期的判断条件") {
                return true;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 同步请求方式,获取最新的Token
     */
    private LoginEntity getNewToken() throws IOException {
        // 通过一个特定的接口获取新的token,此处要用到同步的retrofit请求
        Call<LoginEntity> loginCall = RetrofitHelper.getInstance().getRetrofit(Api.class)
                .getToken("参数");
        return loginCall.execute().body();
    }
然后在OkHttp中配置

okHttpClient = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)//连接超时
        .readTimeout(15, TimeUnit.SECONDS)//读取超时
        .writeTimeout(15, TimeUnit.SECONDS)//写入超时
        .addInterceptor(new TokenInterceptor())//okhttp拦截器 Application拦截
        .build();

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值