美文网首页AndroidWorldAndroid进阶App
OkHttp实现全局过期token自动刷新

OkHttp实现全局过期token自动刷新

作者: fancy_boy_石嘉成 | 来源:发表于2018-03-29 22:57 被阅读1088次

    问题

    一次面试遇到的一个问题,其实也是实际开发中很容易遇到的问题,特此记录一下。

    当请求某个接口的时候,我们会在请求的header中携带token消息,但是发现token失效,接口请求报错,怎么马上刷新token,然后重复请求方才那个接口呢?这个过程应该说对用户来说是无感的。

    这个过程用流程图可以这样表示:

    自动更新token流程

    要实现上述需求的话,大家会如何实现呢?

    首先讲一下Token和Cookie吧

    - cookie

    cookie是保存在本地终端的数据。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

    cookie的组成有:名称(key)、值(value)、有效域(domain)、路径(域的路径,一般设置为全局:"")、失效时间、安全标志(指定后,cookie只有在使用SSL连接时才发送到服务器(https))。

    - token

    token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库。

    解决方案

    1. 通过拦截器,获取返回的数据
    2. 判断token是否过期
    3. 如果token过期则刷新token
    4. 使用最新的token,重新请求网络数据
    • 自定义自动刷新token的拦截器
    import android.util.Log;
    import java.io.IOException;
    import okhttp3.Interceptor;
    import okhttp3.Request;
    import okhttp3.Response;
    
    /**
     * 自动刷新token的拦截器
     * 
     * @author shijiacheng 
     * @version 1.0
     */
    
    public class TokenInterceptor implements Interceptor {
    
        private static final String TAG = "TokenInterceptor";
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = chain.proceed(request);
            Log.d(TAG, "response.code=" + response.code());
    
            //根据和服务端的约定判断token过期
            if (isTokenExpired(response)) {
                Log.d(TAG, "自动刷新Token,然后重新请求数据");
                //同步请求方式,获取最新的Token
                String newToken = getNewToken();
                //使用新的Token,创建新的请求
                Request newRequest = chain.request()
                        .newBuilder()
                        .header("Authorization", "Basic " + newToken)
                        .build();
                //重新请求
                return chain.proceed(newRequest);
            }
            return response;
        }
    
        /**
         * 根据Response,判断Token是否失效
         *
         * @param response
         * @return
         */
        private boolean isTokenExpired(Response response) {
            if (response.code() == 301) {
                return true;
            }
            return false;
        }
    
        /**
         * 同步请求方式,获取最新的Token
         *
         * @return
         */
        private String getNewToken() throws IOException {
            // 通过获取token的接口,同步请求接口
            String newToken = "";
            return newToken;
        }
    }
    
    
    • 配置下OkHttpUtils
    /**
     * 初始化OkHttpUtils
     */
    public OkHttpUtils(){
        /**
         * 配置OkHttpClient
         */
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(3000, TimeUnit.SECONDS)
                .writeTimeout(3000, TimeUnit.SECONDS)
    //              .cache(new Cache())
    //              .addInterceptor(interceptor)//这里可以继续添加多种拦截器
                .addInterceptor(new TokenInterceptor())//添加获取token的拦截器
                .build();
        
    }
    

    本文作者:shijiacheng
    本文链接: http://shijiacheng.studio/2018/03/28/okhttp-interceptor/
    版权声明:本博客所有文章除特别声明外,均为原创文章。请尊重劳动成果,转载注明出处!

    相关文章

      网友评论

      • Mnnni:这个问题我上家公司有遇到,可以把token设个有效时间,比如15分钟以后就过期,那么现在可以去请求了回来的新token 或者旧token都同样有效,这样对用户来说无感,也不存在并发问题。
      • 丿丶祥灬少:先收藏了,说不定以后会用到
      • e9a44a336dfe:并发问题存在,另外,本地就算没过期,但服务端的token提前失效,或者清理了,也无法请求成功!
      • 沈敏杰:这个存在并发问题
        沈敏杰:@肥肥小浣熊 多个请求并发,报token错误,然后多个请求重新刷token,最后重新发请求以哪个刷回来的token为准?
        江江的大猪:求教为什么会有并发问题

      本文标题:OkHttp实现全局过期token自动刷新

      本文链接:https://www.haomeiwen.com/subject/zuavcftx.html