概述
Android端登陆接口获取一个token 和一个刷新token用的refresh_token,
在接下来的token请求中,所有的接口都需要携带token请求,以便服务端来验证请求的来源是合法的,token的作用是避免频繁请求造成服务压力。而token是具有时效性的,服务端会给他一个时效性,这个时效性有服务器定;如果token是有效的,可以请求成功,而过了这个时间段,这个token就失效了。这时候需要我们使用refresh_token 请求刷新token的接口来获取新的token 和 refresh_token,这样就可以源源不断的保持我们持有的token是有效合法的
设计思想
那么token失效,请求接口失败,那我们该怎么在请求接口请求失败时,请求刷新token之后再重新请求呢,如果按照?这里我会使用OKHttp,相信大家都在使用OKHttp吧?那一定知道OKHttp有Interceptor 拦截器,我的思路是在Interceptor 中拿到响应数据,在根据数据贩毒案token是否失效,如果失效则自动刷新token在重新请求。
我把部分代码亮出来:
Request originalRequest = chain.request();
if (originalRequest.method().equals("POST")) {
Response response = chain.proceed(originalRequest);
if (isTokenExpired(response)) {
FormBody originalFormBody = (FormBody) originalRequest.body();
FormBody.Builder newBuilder = new FormBody.Builder();
for (int i = 0; i < originalFormBody.size(); i++) {
newBuilder.add(originalFormBody.name(i), originalFormBody.value(i));
}
//获取本地refresh_token
String refresh_token = SPUtil.getString(Constants.userinfo.refresh_token, Constants.net.DEFAULT_REFRESH_TOKEN);
HashMap map = new HashMap<>();
map.put("refresh_token", refresh_token);
HttpResult httpResult = new APIFactory(mContext)
.refrashToken(map)
.execute().body();
/**
*如果刷新refresh_token失败,则默认为登陆失效,需要重新登陆
*/
if (httpResult.code != Constants.net.SUCCESS)
throw new APIException(httpResult.code, httpResult.message);
String access_token = httpResult.payload.getResult().getAccess_token();
SPUtil.getString(Constants.userinfo.access_token, access_token);
SPUtil.getString(Constants.userinfo.refresh_token, httpResult.payload.getResult().getRefresh_token());
//添加新token,重新请求
newBuilder.add("token", access_token);
Request newRequest = originalRequest.newBuilder()
.method(originalRequest.method(), newBuilder.build())
.build();
return chain.proceed(newRequest);//重新请求
}
return response;
}
return chain.proceed(originalRequest);
private boolean isTokenExpired(Response response) {
try {
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE);
Buffer buffer = source.buffer();
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
String bodyString = buffer.clone().readString(charset);
HttpResult httpResult = new Gson().fromJson(bodyString, HttpResult.class);
return httpResult.code == Constants.net.LOCAL_TOKEN_INVALID;
}
} catch (IOException e) {
e.printStackTrace();
}
return response.code() == Constants.net.LOCAL_TOKEN_INVALID;
}
代码有注释就不解释了,这里需要注意的是:本来想response.body().string()有坑,当使用该方法那么流会被关闭,在使用就会抛异常。