Android 使用拦截器结合协程实现无感知的 Token 预刷新方案

token拦截器android_Android:给OHTTP添加Interceptor 拦截器 一、前言:1:需求:我们需要对http的请求参数加密,还要对http的返回参数加密,这就需要用到Interceptor 拦截器了。2:OkHttp/Retrofit的实现现在说到网络框架,应该毫无疑问是Retrofit了。上面说的加密方案说到底还是要在网络请求框架内加上,怎么做入侵最小,怎么做最方便才是重点。1、坑定不能直接在接口调用层做加密,加参数,这样每个接口都要修改,这是不可能的。2、Con... 阅读详情

背景

在应用中,我们通常使用 Token 作为用户认证的凭证。为了安全起见,Token 一般设置较短的有效期,并通过 refreshToken 进行续期。传统的做法是当服务端返回 Token 过期的响应(如 401)时,再进行刷新,但这种方式可能导致用户体验不佳(如突然的登录状态丢失、请求失败等)。网上关于 Android 开发中 Token 的无感刷新文章也比较少,且大多是请求失败再进行刷新。因此,我这里提供一种预刷新方案,在 Token 接近过期时提前进行刷新。

Token 刷新相关参数

首先简要说明一下有关 Token 刷新的几个参数。

  • Access Token(访问令牌):一种用于验证客户端请求的短期凭证。当用户登录时,服务器会生成一个访问令牌并将其发送给客户端。客户端在每次请求时将该令牌包含在请求头中,以证明用户的身份。由于访问令牌的有效期较短,因此需要定期刷新。

  • Refresh Token(刷新令牌):一种用于获取新访问令牌的长期凭证。与访问令牌不同,刷新令牌通常具有较长的有效期。当访问令牌过期时,客户端可以使用刷新令牌请求服务器颁发一个新的访问令牌,而无需让用户重新登录。

  • 过期时间:指的是访问令牌和刷新令牌的有效期。访问令牌的过期时间较短,一般为几分钟到一小时不等,而刷新令牌的过期时间较长,通常为几天、几周甚至更久。合理设置过期时间能够在确保安全性的同时,提升用户体验,减少频繁登录的需求。为了进一步提升安全性,当刷新令牌也过期时,用户通常需要重新登录以获取新的凭证。

实现思路

我的目标是确保 Token 在接近过期时无感刷新,避免用户因 Token 过期而体验到任何中断。首先定义一个拦截器,继承自 Interceptor,在这里实现Token的刷新逻辑,并把该拦截器添加到 Retrofit 的拦截器链中。在拦截器中会检查当前的 Token 是否快要过期,如果是,则提前刷新 Token。

具体思路如下:

  1. 提前刷新时间计算:
    在每次请求之前,都会检查 Token 的有效期。如果发现 Token 即将在 5 分钟内过期,就会进行刷新。

  2. 双重锁检查:
    为了避免多个请求同时触发 Token 刷新,导致并发问题,这里使用了双重锁检查的方式来确保只有一个线程会进行 Token 刷新。

  3. 刷新失败处理:
    如果 Token 刷新失败,会引导用户重新登录,并确保用户可以继续正常使用应用。

代码实现

以下是 TokenInterceptor 的具体实现代码:

class TokenInterceptor : Interceptor {
    @RequiresApi(Build.VERSION_CODES.O)
    override fun intercept(chain: Interceptor.Chain): Response {
        val tokenBean = CacheUtil.getToken()
        val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")

        // 检查Token过期时间
        if (!tokenBean.expireTime.isNullOrEmpty()) {
            val expireTime = tokenBean.expireTime.substring(0, 19).let { LocalDateTime.parse(it, formatter) }
            val currentTime = LocalDateTime.now()

            // 提前5分钟刷新Token
            val refreshTime = expireTime.minus(5, ChronoUnit.MINUTES)
            if (expireTime != null && currentTime.isAfter(refreshTime)) {
                synchronized(this) {
                    if (currentTime.isAfter(refreshTime)) { // 双重锁检查
                        runBlocking {
                            val newToken = refreshAuthToken(tokenBean.refreshToken ?: "")
                            newToken?.let { token ->
                                CacheUtil.setToken(token)
                            }
                        }
                    }
                }
            }
        }

        // 添加Token到请求头
        val builder = chain.request().newBuilder().apply {
            addHeader("token", CacheUtil.getToken().token ?: "")
        }
        return chain.proceed(builder.build())
    }

    private suspend fun refreshAuthToken(refreshToken: String): Token? {
        return withContext(Dispatchers.IO) {
            try {
                val response = refreshApi.refreshToken(refreshToken)
                if (response.code == 200 && response.data != null) {
                    response.data
                } else { // refreshToken过期等失败情况
                    handleTokenRefreshFailure()
                    null
                }
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }
    }

    private fun handleTokenRefreshFailure() {
        //处理失败情况,跳转到登录界面
    }
}

协程关键点解析

  • 该拦截器运行在子线程中,通过 runBlocking 阻塞当前线程并调用 refreshAuthToken 方法,挂起当前协程,等待 newToken 返回。
  • withContext 同样会挂起当前函数,使得 refreshAuthToken 能够返回 withContext(Dispatchers.IO) 中获取的结果。
  • refreshApi.refreshToken(refreshToken) 是一个挂起函数,结合 Retrofit 可以实现挂起并等待结果返回。
  • 通过一系列的挂起,在if (currentTime.isAfter(refreshTime))条件内实现了对 Token 的请求刷新,刷新完毕后 builder 会添加最新的 Token 继续执行当前被挂起的网络请求。

流程图

拦截器流程图

误区提示

注意不要使用相同的 Retrofit 实例构建 refreshApi 和正常请求的代理对象。 正常请求的 Retrofit 对象中包含自定义的 TokenInterceptor 拦截器,如果 refreshApi 也使用了这个 Retrofit 对象,刷新 Token 的请求将被拦截器捕获,导致递归调用并陷入无限循环。因此,必须使用不带 TokenInterceptor 的 Retrofit 实例来构建刷新 Token 的代理对象。

总结

实测结果显示,在 Token 过期时,多个请求并发执行刷新逻辑时,用户几乎不会察觉到任何延迟。通过这种无感知的 Token 预刷新方案,可以有效减少 Token 过期带来的请求失败问题,同时提升了用户的体验。如果你也在处理类似的需求,希望这个方案能给你带来帮助,也欢迎一起讨论实现方案和技术细节。

Android -Token刷新机制与UDP优化 本文介绍了三种Android开发中常用的Token刷新机制:主动刷新(请求前检查令牌有效期)、被动刷新(收到401错误后触发)和基于AccountManager的系统级刷新。重点分析了QUIC协议如何基于UDP解决TCP的三大痛点:通过合并握手实现0-RTT连接、多流机制消除队头阻塞、连接ID实现网络切换不中断。QUIC在应用层实现了可靠传输、拥塞控制等TCP特性,并与HTTP/3深度整合,为现代移动互联网提供了更快速、可靠的传输方案。 阅读详情

相关推荐

电赛备赛笔记:用STM32驱动AD9959信号发生器模块,从接线到出波保姆级教程

本文详细介绍了如何使用STM32驱动AD9959信号发生器模块,从硬件接线到软件调试的全流程。AD9959作为高性能DDS芯片,适用于电子设计竞赛中的信号生成需求。文章包含硬件连接指南、寄存器配置解析、多通道控制技巧以及常见问题解决方案,帮助参赛者快速掌握AD9959的应用。

weixin_31858171的博客 366

Android 拦截器判断Token是否过期

public class TokenInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); ResponseBody respo.

weixin_42630638的博客 2563

ali140滑块

ali 140滑块采用补环境的方式进行逆向,需要的文件主要为这两个,其中collina.js是最主要的环境校验和参数加密的逻辑,这两个文件放本地进行补环境。然后挂上代理,先保证能够正常运行代码,补了些许后能够正常运行了,我们打印最主要的加密函数看看:n值就是得到:挂上代理看看鼠标事件,不管加密逻辑,关心入参即可:收集一些鼠标事件传进记录的函数。其余就是处理一些环境值,一些resetSA的逻辑就行。截图记录:

bboysteed的博客 1676

Android — 使用Interceptor和协程实现自动刷新token

在应用端和后端交互时,有些特定的接口需要验证token才能返回正确的结果,例如修改用户信息、获取用户信息等。token通常会设定一个有效期,在有效期内使用才能正常获取结果。当token过期时,用户体验可能受到影响,可以在token过期后自动刷新token优化用户体验。本文简单介绍一下如何使用和协程实现自动刷新token。

Gaga246的博客 750

射频总集篇:(不断更新)

射频每一章涉及到的重点理论/设计方法 CHAPTER 1 传输线理论 输入阻抗Zin,负载阻抗ZL,驻波比ρ,反射系数 CHAPTER 2 波导 矩形波导,圆波导,同轴线 CHAPTER 3 微型带状传输线 微带线的参数设计,带状线的参数设计 CHAPTER 4 ...

jieyannn的博客 1919

从硬件异常到代码救赎:RH850内存访问错误(MAE)的深层诊断与艺术

本文深入探讨瑞萨RH850微控制器的内存访问错误(MAE)诊断与解决方法。针对程序跑飞和Flash Driver交互中的潜在陷阱,提供系统性硬件异常分析框架和防御性编程实践,帮助嵌入式开发者从底层机制到代码层面有效预防和修复MAE问题,提升系统稳定性。

pytorch8learner的博客 195

Android Retrofit处理Token过期的问题

Retrofit处理Token过期的问题

zjuter的专栏 3273

整合Springboot+MybatisPlus+达梦数据库

整合Springboot+MybatisPlus+达梦数据库,以及一些坑

波波的博客 6677

Android-使用OKHTTP Interceptor刷新Access-Token

sdgsg

ShiShouFeng 2108

Vivado实战:如何用BUFGMUX_CTRL实现FPGA双时钟热切换(附时序约束模板)

本文详细介绍了如何使用Xilinx FPGA中的BUFGMUX_CTRL原语实现双时钟热切换的工业级解决方案。通过分析BUFGMUX_CTRL的核心机制、PCB布局约束和电源噪声抑制方法,提供Vivado实现全流程和时序约束模板,帮助工程师在工业自动化、车载电子等场景中提升系统可靠性。

weixin_29186249的博客 572

Python学习第1天:初识Python

Python 作为目前最流行的编程语言之一,凭借其简洁优雅的语法和强大的生态系统,成为了无数开发者的首选。本系列文章将带你从零基础入门,逐步掌握 Python 编程的核心技能。今天我们先来认识 Python,并安装好开发环境。Python(英式发音:/ˈpaɪθən/;美式发音:/ˈpaɪθɑːn/)是由荷兰人吉多·范罗苏姆(Guido von Rossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户的编程语言。

tigerhhzz的博客 433

Android使用拦截器结合协程实现无感知的Token预刷新方案

本文提出了一种Token预刷新方案,在Token接近过期时提前刷新以避免用户登录中断。方案采用拦截器实现,通过双重锁检查确保线程安全,并在刷新失败时引导用户重新登录。关键点包括:提前5分钟计算刷新时间、使用独立Retrofit实例防止循环调用、通过协程机制实现异步刷新。该方案能有效提升用户体验,避免传统Token过期导致的请求失败问题。实现代码以Kotlin编写,适用于Android平台。

ChenYiRan123456的博客 867

如何使用PostgreSQL数据库进行数据仓库的ETL操作

本文旨在为数据工程师、数据库管理员和分析师提供使用PostgreSQL进行数据仓库ETL操作的全面指南。ETL流程的基本原理PostgreSQL在ETL中的独特优势实际ETL实现的技术细节性能优化和最佳实践常见问题的解决方案首先介绍ETL和PostgreSQL的基本概念然后深入探讨核心技术和实现方法接着提供实际案例和代码示例最后讨论优化技巧和未来趋势ETL:提取(Extract)、转换(Transform)、加载(Load)的缩写,描述数据从源系统移动到目标数据仓库的过程。

2502_91592937的博客 873

token拦截器android_Android OkHttp实现全局过期token自动刷新示例

问题一次面试遇到的一个问题,其实也是实际开发中很容易遇到的问题,特此记录一下。当请求某个接口的时候,我们会在请求的header中携带token消息,但是发现token失效,接口请求报错,怎么马上刷新token,然后重复请求方才那个接口呢?这个过程应该说对用户来说是无感的。这个过程用流程图可以这样表示:自动更新token流程要实现上述需求的话,大家会如何实现呢?首先讲一下Token和Cookie吧-...

weixin_33610824的博客 1114

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android网络请求 —— Token拦截器(保证多个请求同时执行时候,成功拦截)

在App执行网络请求的场景中,经常需要用到Token作为合法访问身份识别码,设置到Header中传递给后台。且token往往是有效期的,这个时候,就需要用到 OkHttp的拦截器,对请求是否需要携带token做验证,并对token是否有效做验证,且在必要的时候重新获取合法token。 直接进入正题,token拦截器一共做了两件事情:1,对请求接口做判断,是否需要携带token;2,对token合...

qingjuyashi的博客 5346

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

token拦截器android_OkHttp3拦截器使用(统一添加header、统一处理Token过期等)

为了保证Http请求的安全性,最近开发的项目采用了OAuth2.0认证机制,在Http请求头中加入了参数签名和accessToken进行验证。这样就带来几个问题:n多请求,如何做到统一签名?accessToken过期后,如何Hold当前请求,进行token的无感刷新?accessToken刷新后,如何直接进行原始请求的重发?其实,使用OkHttp的Interceptors(拦截器)便可以优雅的解决...

weixin_32955881的博客 3573

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

android token机制_Android OkHttp实现全局过期token自动刷新示例

问题一次面试遇到的一个问题,其实也是实际开发中很容易遇到的问题,特此记录一下。当请求某个接口的时候,我们会在请求的header中携带token消息,但是发现token失效,接口请求报错,怎么马上刷新token,然后重复请求方才那个接口呢?这个过程应该说对用户来说是无感的。这个过程用流程图可以这样表示:自动更新token流程要实现上述需求的话,大家会如何实现呢?首先讲一下Token和Cookie吧-...

weixin_30814159的博客 982

基于OkHttp拦截器实现Token自动刷新(kotlin实现)

基于OkHttp拦截器实现Token自动刷新

追风筝的人 1622

Android 刷新Token Retrofit Token过期 重新请求Token再去请求接口

需求是这样的:请求接口A -- 服务器返回数据Token过期或失效  -- 重新请求Token并设置 -- 再去请求接口A刚解决了这个问题,趁热打铁,写个博客记录一下;这个Token是添加到请求头里面的;使用OKHTTP设置Retrofit中的请求头:*记录请求到的Token/** * 请求头token * @return */ public String headerToken = "";...

Choi晨的博客 4131

token拦截器android_用好okhttp拦截器 自动添加Token

环境和项目情况大部分APP应用都用Retrofit + mvp +Rxjava来实现。其中Retrofit实际上用了Okhttp。有了okhttp自然而然想到了拦截器。说到拦截器,就是对每一个访问(Request)的拦截,打个比方,就好比请求发出去之前,先让我过滤(加工)一下,比如Header里面我统一处理一下啥的(比如每个请求都加个Token啥的)。Retrofit 和okhttp拦截器功能强大...

weixin_29184075的博客 1186

android token机制_Android网络实战篇——Token添加、过期判定以及处理(全局自动刷新)...

Android日常开发中网络请求必不可少,一般来说每一个接口API都会设置Token,用来验证和做唯一识别,Token都会设置一个有效时间,那么Token失效了怎么办?怎样来更新Token?首先怎样来判断Token失效呢?与后端约定,保存到本地,约定时间到了就判定Token已过期后端返回HTTP Code 401,客户端接到401后判定Token已过期后端返回与客户端约定的自定义Code,客户端接...

weixin_34997006的博客 2154

token 过期刷新令牌_OkHttp实现全局过期token自动刷新

问题一次面试遇到的一个问题,其实也是实际开发中很容易遇到的问题,特此记录一下。当请求某个接口的时候,我们会在请求的header中携带token消息,但是发现token失效,接口请求报错,怎么马上刷新token,然后重复请求方才那个接口呢?这个过程应该说对用户来说是无感的。这个过程用流程图可以这样表示:自动更新token流程要实现上述需求的话,大家会如何实现呢?首先讲一下Token和Cookie吧-...

weixin_39954698的博客 356

Android开发 Retrofit实现token失效刷新的处理方案

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33797791的博客 1427

实现无感刷新token我是这样做的

前言 最近在做需求的时候,涉及到登录token,产品提出一个问题:能不能让token过期时间长一点,我频繁的要去登录。 前端:后端,你能不能把token 过期时间设置的长一点。 后端:可以,但是那样做不安全,你可以用更好的方法。 前端:什么方法? 后端:给你刷新token的接口,定时去刷新token 前端:好,让我思考一下 需求 当token过期的时候,刷新token,前端需要做到无感刷新token,即刷token时要做到用户无感知,避免频繁登录。 实现思路 方法一 后端返回过期时间,前端判断token过

weixin_43854764的博客 268

Vue + Spring Security项目里,我是这样用Axios拦截器优雅刷新JWT Token的

本文详细介绍了在Vue + Spring Security项目中,如何利用Axios拦截器实现JWT Token的无感刷新机制。通过双Token设计、请求队列管理和防并发刷新等核心技巧,有效解决了用户会话中断问题,提升前后端交互体验。特别针对refresh_token的实时刷新场景,提供了完整的代码实现和优化方案。

weixin_30635053的博客 320

Net拦截器与重试机制:提升Android网络请求成功率的关键技巧

Net作为一款基于协程和OkHttp的Android网络请求工具,其拦截器与重试机制是保障网络请求稳定性的核心功能。本文将详细介绍如何通过这两个功能解决网络波动、token过期等常见问题,让你的App在复杂网络环境下依然保持高效请求能力。 ## 拦截器:请求的智能管家 🛡️ 拦截器是Net框架中处理请求/响应的重要组件,能够在请求发送前和响应返回后进行自定义处理。Net提供两种拦截器类型,满

gitblog_00591的博客 966
上一篇: Android高德地图SDK内存泄漏排查记录
debug_ww
博客等级 码龄4年 17粉丝 2原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值