Android中使用Retrofit刷新Token
实际开发中,例如登录,我们向后台传参用户名和密码,后台会返回给我们一个Token,用于后面接口的调用,
这样后端就能通过我们传入的token知道我们是哪个用户,一般token的有效期是2小时。2小时候token会自动过期。我们需要拿到新的Token,保持登陆状态。
如何刷新Token呢
如上图所示,我们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;
}
}