本blog文章为ShiShouFeng原创文章,如需转载引用请注明出处,谢谢
https://blog.csdn.net/ForwardSailing/article/details/106449790
Android-使用OKHTTP Interceptor刷新Access-Token
Android-使用OKHTTP Interceptor刷新Access-Token
前言
Token设计
一般软件设计为保证安全服务器端引入Token令牌校验,客户端在发起网络请求时,需要在请求头中携带 Token 令牌信息,服务端对 Token 令牌进行校验,校验 Token合法且 Token超过有效期 服务端会返回相应数据,如果不合法 或 Token失效情况下会 HTTP Status 返回 401 或 接口返回信息中 code 相应错误码 (我们以返回 -10001为例)
为提高用户体验,避免因 AccessToken 失效而导致用户重新登录,所以客户端需要在 AccessToken 失效后 使用 Refresh Token 请求刷新Token接口,改接口会重新返回一个 AccessToken 、RefreshToken 等信息。
注意:客户端一般情况需要把接口返回信息保存在本地
现在考虑有如下业务场景:
用户想要获取 商品信息(/get/shop/details.v1.0) 但是接口返回Token失效,此时需要用刷新Token (/refresh/token.v1.0) 接口获取新的AccessToken,之后将新的Token添加到 获取商品信息接口中,之后再重新请求接口。
在上面的业务场景中,如果使用OKhttp 的 Interceptor 拦截器实现就比较简单了,下面看一下具体该怎么做。
使用OKhttp Tnterceptor 刷新 Token
Interceptor 是什么
Interceptor
是OKhttp 中 利用责任链设计模式设计的、链式请求和返回结果的链式调用,Interceptor
分为两种责任链,分别是:
- Application Interceptor
- Network Interceptor
这两者本身实现上并没有差别,唯一的区别是 工作的层次不同,Application 级 Interceptor 会首先执行,返回结果后最后执行,而 Network 级 Interceptor 是工作在 发起网络请求前执行,如下图所示:
如何使用拦截器
添加 Application Interceptor 拦截器
添加 Application Interceptor 拦截器 只需要获取 OKHttpClient
对象 调用 addInterceptor
方法即可
public Builder addInterceptor(Interceptor interceptor) {
if (interceptor == null) throw new IllegalArgumentException("interceptor == null");
interceptors.add(interceptor);
return this;
}
添加 Network Interceptor 拦截器
添加 Network Interceptor 拦截器 只需要获取 OKHttpClient
对象 调用 addNetworkInterceptor
方法即可
public Builder addNetworkInterceptor(Interceptor interceptor) {
if (interceptor == null) throw new IllegalArgumentException("interceptor == null");
networkInterceptors.add(interceptor);
return this;
}
添加的拦截器是什么时候执行的?
上面我们知道了两种拦截器添加方式,那么添加的拦截器是什么时候执行的呢?添加的拦截器最终会调用到 RealCall
类中的 getResponseWithInterceptorChain()
如下:
-
①处:Application 级别 Interceptor 在每次执行网络请求时 就添加至 责任链中
-
②处:在网络真正发起前将 Network 级 Interceptor 添加至拦截器中
上面添加Network 级 Interceptor 受 forWebSocket 变量控制,不过在默认情况下使用 forWebSocket 这个变量都是 false
自定义 Interceptor 刷新 Token
前面我们 我们知道了 Interceptor
是什么以及如何使用 Interceptor
、接下来我们就利用 Interceptor
来实现我们的业务:
实现刷新Token的Interceptor
我们创建TokenInterceptor
并实现intercept()
实现以下逻辑:
/**
* Created by shishoufeng on 2019/4/16.
* <p>
* desc : token 拦截器 用于校验 token 是否失效 如果失效需要 及时更新 token
* <p>
*/
public class TokenInterceptor implements Interceptor{
private static final String TAG = "TokenInterceptor";
private static final Charset UTF8 = Charset.forName("UTF-8");
private Context mContext;