kotlin之Token刷新

前面介绍了kotlin之RxJava2+Retrofit2,现在就部分项目中遇到的Token刷新问题做个思路。

Token是指个别项目中引入的请求令牌,在首次登陆后会得到一个随机字符串,这个随机字符串有一定的时间限制,过期后需要使用特定的字符串去刷新这个token以保证后续的接口能够正常访问。

这里有两种解决方案,一种是使用okhttp提供Authenticator类,这种方式只适用于服务器将鉴权失败以状态码的方式返回。另一种就是添加拦截器,适用于认定鉴权失败时正常的业务请求,返回状态码依然是200。

方案一

先上干货

class TokenAuthenticator : Authenticator {
    override fun authenticate(route: Route?, response: Response?): Request? {
        val refreshToken = Utils.defaultSP.getString(Constants.KEY_REFRESH_TOKEN, null)
        var newToken: String? = null
        //这里使用同步的方式去获取新的token
        if (refreshToken != null) newToken = ApiService.default().refreshToken(refreshToken).execute().body()
        
        return if (newToken != null) {
            Utils.defaultSP.edit().putString(Constants.KEY_ACCESS_TOKEN, newToken).apply()
            response?.request()?.newBuilder()?.header("Authentication", newToken)?.build()
        } else {
            response?.request()
        }
    }
}


 okHttpBuilder.authenticator(authenticator)

覆写Authenticator 类后,并在构建okhttpclient的时候可以添加进去。在网络请求返回后如果状态码是401则会回调authenticate方法,在这个方法中我们需要做的就是利用refresh_token字符串去获取新的Token。如果拿到了新的token则将新的token替换到原本请求头中的字段再发起一次请求,如果没有拿到新的token则返回原来的请求。

方案二

class TokenInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain?): Response {
        val originalRequest = chain?.request()
        val response = chain?.proceed(originalRequest)

        val json = response?.body().toString()
        if (!TextUtils.isEmpty(json)) {
            val obj = JSONObject(json)
            if (obj.has("code") && obj.getInt("code") == Constants.NET_CODE_TOKEN_EXPIRE) {
                val refreshToken = Utils.defaultSP.getString(Constants.KEY_REFRESH_TOKEN, null)
                var newToken: String? = null
                if (refreshToken != null) newToken = ApiService.default().refreshToken(refreshToken).execute().body()

                if (newToken != null) {
                    Utils.defaultSP.edit().putString(Constants.KEY_ACCESS_TOKEN, newToken).apply()
                    val requestBuilder = originalRequest?.newBuilder()?.header("Authentication", newToken)
                    return chain!!.proceed(requestBuilder?.build())
                }
            }
        }
        return response!!
    }
}

okHttpBuilder.addInterceptor(interceptor)

以上是使用拦截器的方式来监听网络请求的结果,判断业务码是某个值时发起刷新Token的网络请求,顺利拿到新的token后替换掉原来请求头的字段,并再次发起请求。

总结

以上是目前认为比较简单的处理刷新token的方式,个人更推荐第二种方式一点,但也要结合实际的需求,如果有更好的方式,可以和我探讨我在补充出来分享给大家。

你可能感兴趣的:(kotlin之Token刷新)