安卓开发安卓开发Android开发经验谈

retrofit+okhttp+coroutines拦截Toke

2019-07-02  本文已影响10人  蓝不蓝编程

背景

Token是当前用于客户端到服务端做身份验证的一种较为常见的机制. 客户端先通过用户名、密码登陆服务器,获取token,后续每次请求都带上token.当token在有效期内,服务器都校验通过,失效后,则返回鉴权失败,客户端需要重新登陆获取token. 如果过一段时间就需要用户登陆一次,这显然非常不友好.那怎么办呢?

解决方案

  1. 方案一、token设置为永远有效.
    这显然是下下招,一旦token被人截获,就被人玩死了.
  2. 方案二、app启动就检查token是否将要失效,如果是,则自动登陆刷新token,app运行中,也定时检查并刷新token.
  3. 方案三、每次请求前,都判断token是否将要失效,如果是,则自动登陆刷新token,然后再发出原请求.
  4. 方案四、Token失效拦截. 对所有请求(除登陆请求)进行拦截,如果token失效,则自动登陆刷新token,然后再发出原请求. 本文仅介绍此方案的具体实现方式.

Token失效拦截实现方法

  1. 为okhttp设置拦截器
    其中HttpHeaderInterceptor是为所有请求添加token字段的拦截器;TokenInterceptor是检测token是否失效并重新登陆的拦截器.
OkHttpClient.Builder()
.apply {
    addInterceptor(HttpHeaderInterceptor())
    addInterceptor(TokenInterceptor())
}.build()
  1. token拦截器中,需对返回信息做判断,看是否失效.如果失效,则自动登陆,然后重新执行原请求.注意:自动登陆时,不能再采用coroutines异步执行,必须要用同步方式,才能登陆后执行原请求并返回执行结果给调用者.
class TokenInterceptor : Interceptor() {
    override fun interceptMe(chain: Interceptor.Chain): Response {
        val request = chain.request()
        var response = chain.proceed(request)
        if (isTokenExpired(response)) {
            LoginManager.login(
                    onSuccess = {
                        val newRequest = replaceTokenInHeader(request, it.token)
                        response?.close()
                        response = chain.proceed(newRequest)
                    }
            )
        }
        return response
    }

    /**
     * 判断token是否失效。
     * TODO: 下面函数isTokenExpired只是测试样例,固定返回true;应根据实际项目修改。
     */
    private fun isTokenExpired(response: Response) = true//(response.code() == TOKEN_EXPIRED)
}

Demo源代码

https://gitee.com/cxyzy1/coroutineRetrofitDemo.git

安卓开发技术分享: https://www.jianshu.com/p/442339952f26
点击关注专辑,查看最新技术分享
更多技术总结好文,请关注:「程序园中猿」

上一篇 下一篇

猜你喜欢

热点阅读