基于Retrofit拦截器的自动登陆

来源:互联网 发布:在美橙互联域名备案 编辑:程序博客网 时间:2024/04/30 03:49

在开发电商类项目的时候,都要保持登陆状态,避免用户的反复登陆,当然要实现这种逻辑有很多种方法,我就说下我在项目中用拦截器实现的自动登陆

我们项目是直接将token信息放到header里,token的有效期是三十分钟,如果token失效,再根据服务器返回来的code,来判断,再通过自动登陆接口,获取新的token放到header里,并生成新的request 请求服务器,如果你的项目服务器也是这样操作的,可以借鉴下我的代码:

先看下自己创建的服务器交互类,里面一般会封装服务器请求接口和单利实例,最主要的还是创建拦截器:

//设置拦截器,对请求参数做签名处理Interceptor interceptor = new Interceptor() {    @Override    public Response intercept(Chain chain) throws IOException {        Request request = chain.request();        // 新的请求        Request newRequest = null;        String token = SpUtil.getInstance(context).getStringValue("token");        if (oldBody instanceof FormBody) {            if (!TextUtils.isEmpty(token)) {        //token没失效,继续用                newRequest = request.newBuilder().url(request.url()).post(formBuilder.build()).header("token", token).build();            } else{                newRequest = request.newBuilder().url(request.url()).post(formBuilder.build()).build();            }        }        //以下代码是签名之后需要使用的代码,不需要签名请注释        Response response = chain.proceed(newRequest);   return response;    }};
第一个拦截器,最主要的目的就是把token放到请求头里面,不用每次请求的时候都在去加上token;

  private class TokenInterceptor implements Interceptor {        private Context context;        public TokenInterceptor(Context context){            this.context = context;        }        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            // try the request            Response originalResponse = chain.proceed(request);            /**通过如下的办法曲线取到请求完成的数据             *             * 原本想通过  originalResponse.body().string()             * 去取到请求完成的数据,但是一直报错,不知道是okhttp的bug还是操作不当             * 取到请求完成的数据后,根据特定的判断条件去判断token过期             */            ResponseBody responseBody = originalResponse.body();            BufferedSource source = responseBody.source();            source.request(Long.MAX_VALUE); // Buffer the entire body.            Buffer buffer = source.buffer();            Charset charset = UTF8;            MediaType contentType = responseBody.contentType();            if (contentType != null) {                charset = contentType.charset(UTF8);            }            String bodyString = buffer.clone().readString(charset);            ResultVo vo = GsonUtil.deser(bodyString, ResultVo.class);            if (vo.result == 0) {                 //token失效                     LogUtil.e("静默自动刷新Token,然后重新请求数据");                String code = SpUtil.getInstance(context).getStringValue("code");                if (!TextUtils.isEmpty(code)){                // 通过一个特定的接口获取新的token,此处要用到同步的retrofit请求                Call<ResultVo> call = NetworkService.getInstance().getAPI().autoLogin(code);                //要用retrofit的同步方式                ResultVo response = call.execute().body();                if(response.result==0){                    Intent intent = new Intent(context,LoginActivity.class);                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                    context.startActivity(intent);                    return originalResponse;                }else{                    String newToken = call.clone().execute().body().token;          //call只能有一个                    LogUtil.e("newToken"+newToken);                    SpUtil.getInstance(context).setValue("token",newToken);                    // create a new request and modify it accordingly using the new token                    Request newRequest = chain.request().newBuilder().header("token", newToken).build();                    // retry the request//                    originalResponse.body().close();                    return chain.proceed(newRequest);                }                }            }            return originalResponse;        }    }

这是自己建的token拦截器,实现Interceptor接口,然后根据拿到的response解析到里面的我们想要的数据,再根据服务器返回的result来进行判断,这里的0是服务器返回的,所以具体情况具体分析,这里我是用sharepreference来保存token和code,是有隐患的,所以可以用其他方法替代,但是思想一致,拿到我们在登陆的时候服务器返回的code,调用自动登陆接口,前提是用户已经登陆过,这时候再判断下result,因为可能用户会在PC 或者其他方式修改过密码,确认result无误后,我们在保存新token的同时,将新的token放到请求头里,并传给服务器,就完成了简单的自动登陆功能,但此方法有局限性且用SP 有隐患。






0 0
原创粉丝点击