当前位置: 首页 > article >正文

5分钟搞定前后端无感刷新:accessToken与refreshToken实战指南(含axios拦截器配置)

5分钟搞定前后端无感刷新accessToken与refreshToken实战指南含axios拦截器配置在当今的Web应用开发中用户认证是一个绕不开的话题。传统的单token方案虽然简单但当token过期时强制用户重新登录的体验实在称不上优雅。想象一下用户正在填写一个复杂的表单突然因为token过期而被踢出系统所有输入的内容都丢失了——这种体验足以让用户对产品产生负面印象。无感刷新机制正是为了解决这一问题而生。通过accessToken和refreshToken的巧妙配合我们可以在用户毫无感知的情况下完成token的更新保持会话的连续性。本文将聚焦于中小型项目的快速实现方案提供一套即插即用的解决方案让你在5分钟内就能为项目添加这一重要功能。1. 理解双token机制的核心原理在开始编码之前我们需要先理解accessToken和refreshToken这对搭档是如何协同工作的。accessToken就像是一张短期通行证有效期通常较短如15分钟到2小时用于日常的API请求认证。而refreshToken则是一张长期通行证有效期可达数天甚至数周专门用于在accessToken过期时获取新的accessToken。这种设计有几个关键优势安全性即使accessToken被截获攻击者也只能在短时间内滥用用户体验避免了频繁要求用户重新登录的困扰灵活性可以随时调整refreshToken的有效期或撤销特定设备的refreshToken提示虽然refreshToken有效期较长但并不意味着可以无限期使用。合理的做法是设置一个适中的有效期如7天并在用户主动退出时立即撤销所有refreshToken。2. 前端实现axios拦截器配置axios的拦截器功能为我们实现无感刷新提供了完美的工具。下面是一个完整的实现方案// 创建axios实例 const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use( config { const accessToken localStorage.getItem(accessToken) if (accessToken) { config.headers[Authorization] Bearer ${accessToken} } return config }, error { return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response { return response.data }, async error { const originalRequest error.config // 检查是否是token过期错误 if (error.response.status 401 !originalRequest._retry) { originalRequest._retry true try { // 尝试刷新token const refreshToken localStorage.getItem(refreshToken) const res await axios.post(/auth/refresh, { refreshToken }) // 存储新的accessToken localStorage.setItem(accessToken, res.data.accessToken) // 重试原始请求 originalRequest.headers[Authorization] Bearer ${res.data.accessToken} return service(originalRequest) } catch (refreshError) { // 刷新失败跳转到登录页 localStorage.removeItem(accessToken) localStorage.removeItem(refreshToken) router.push(/login) return Promise.reject(refreshError) } } return Promise.reject(error) } )这段代码实现了以下功能在请求头中自动添加accessToken检测401错误token过期自动使用refreshToken获取新的accessToken重试原始请求处理刷新失败的情况3. 后端实现简洁高效的token管理后端需要提供两个关键接口登录接口和刷新接口。以下是使用Node.js和Express的实现示例const jwt require(jsonwebtoken) const redis require(redis) // 配置 const config { accessTokenSecret: your_access_secret, refreshTokenSecret: your_refresh_secret, accessTokenExpiry: 15m, refreshTokenExpiry: 7d } // Redis客户端 const redisClient redis.createClient() redisClient.on(error, (err) console.log(Redis Client Error, err)) // 登录接口 app.post(/login, (req, res) { const { username, password } req.body // 验证用户凭据简化示例 if (username ! admin || password ! password) { return res.status(401).json({ error: Invalid credentials }) } // 生成token const accessToken jwt.sign({ username }, config.accessTokenSecret, { expiresIn: config.accessTokenExpiry }) const refreshToken jwt.sign({ username }, config.refreshTokenSecret, { expiresIn: config.refreshTokenExpiry }) // 存储refreshToken到Redis redisClient.set(refreshToken, username) redisClient.expire(refreshToken, 60 * 60 * 24 * 7) // 7天 res.json({ accessToken, refreshToken }) }) // 刷新接口 app.post(/auth/refresh, (req, res) { const { refreshToken } req.body // 验证refreshToken jwt.verify(refreshToken, config.refreshTokenSecret, (err, decoded) { if (err) { return res.status(401).json({ error: Invalid refresh token }) } // 检查Redis中是否存在该refreshToken redisClient.get(refreshToken, (err, reply) { if (!reply) { return res.status(401).json({ error: Refresh token expired }) } // 生成新的accessToken const newAccessToken jwt.sign( { username: decoded.username }, config.accessTokenSecret, { expiresIn: config.accessTokenExpiry } ) res.json({ accessToken: newAccessToken }) }) }) })这个实现包含了几个关键点使用不同的密钥和有效期生成accessToken和refreshToken将refreshToken存储在Redis中以便验证和管理提供清晰的错误响应4. 常见问题与解决方案在实际应用中你可能会遇到以下问题4.1 并发请求导致的多次刷新当多个请求同时收到401错误时可能会触发多次刷新请求。解决方案是let isRefreshing false let failedQueue [] const processQueue (error, token null) { failedQueue.forEach(prom { if (error) { prom.reject(error) } else { prom.resolve(token) } }) failedQueue [] } service.interceptors.response.use( response response, async error { const originalRequest error.config if (error.response.status 401 !originalRequest._retry) { if (isRefreshing) { return new Promise((resolve, reject) { failedQueue.push({ resolve, reject }) }).then(token { originalRequest.headers[Authorization] Bearer token return service(originalRequest) }).catch(err { return Promise.reject(err) }) } originalRequest._retry true isRefreshing true try { const refreshToken localStorage.getItem(refreshToken) const res await axios.post(/auth/refresh, { refreshToken }) localStorage.setItem(accessToken, res.data.accessToken) processQueue(null, res.data.accessToken) originalRequest.headers[Authorization] Bearer res.data.accessToken return service(originalRequest) } catch (error) { processQueue(error, null) localStorage.removeItem(accessToken) localStorage.removeItem(refreshToken) router.push(/login) return Promise.reject(error) } finally { isRefreshing false } } return Promise.reject(error) } )4.2 安全性最佳实践为了确保token机制的安全性建议遵循以下原则安全措施实施方法作用HTTPS全站启用HTTPS防止token在传输中被窃取HttpOnly Cookie将refreshToken存储在HttpOnly Cookie中防止XSS攻击窃取token短期有效期accessToken设置较短有效期15-120分钟减少token泄露后的风险窗口密钥轮换定期更换签名密钥降低密钥泄露的影响黑名单维护已撤销但未过期的token列表及时阻止被撤销的token4.3 性能优化对于高并发应用可以考虑以下优化批量验证当需要验证多个token时使用Redis的批量操作命令本地缓存在内存中缓存有效的token减少Redis查询连接池使用Redis连接池提高连接复用率5. 测试与调试技巧确保你的无感刷新机制正常工作至关重要。以下是一些测试建议手动测试流程登录获取token等待accessToken过期或手动修改使其过期发起API请求观察是否自动刷新检查新token是否被正确存储和使用自动化测试脚本describe(Token Refresh, () { let accessToken, refreshToken before(async () { // 登录获取初始token const res await request(app) .post(/login) .send({ username: test, password: test }) accessToken res.body.accessToken refreshToken res.body.refreshToken }) it(should refresh token when expired, async () { // 模拟token过期 const expiredToken jwt.sign( { username: test }, your_access_secret, { expiresIn: -1s } ) // 设置过期的token localStorage.setItem(accessToken, expiredToken) // 发起请求 const res await service.get(/protected) // 验证 expect(res.status).toBe(200) expect(localStorage.getItem(accessToken)).not.toBe(expiredToken) }) })调试工具使用Chrome开发者工具查看网络请求在拦截器中添加console.log调试关键步骤使用Redis CLI监控token存储情况在实际项目中我发现设置合理的token过期时间非常重要。accessToken太短会导致频繁刷新太长则安全性降低。经过多次测试15-30分钟的accessToken配合7天的refreshToken在大多数场景下都能取得良好的平衡。

相关文章:

5分钟搞定前后端无感刷新:accessToken与refreshToken实战指南(含axios拦截器配置)

5分钟搞定前后端无感刷新:accessToken与refreshToken实战指南(含axios拦截器配置) 在当今的Web应用开发中,用户认证是一个绕不开的话题。传统的单token方案虽然简单,但当token过期时强制用户重新登录的体验实在称不上优…...

高通平台Android Display调试指南:常见问题与解决方案汇总

高通平台Android Display调试实战:从硬件兼容到框架优化的全链路解决方案 在移动设备开发领域,Display模块的稳定性直接影响用户体验,而高通平台作为Android生态的核心硬件基础,其显示系统的调试复杂度往往令开发者望而生畏。本文…...

CubeMX配置FreeRTOS时基终极指南:如何根据项目需求选择SysTick或TIM6/7

CubeMX配置FreeRTOS时基终极指南:如何根据项目需求选择SysTick或TIM6/7 在嵌入式系统开发中,实时操作系统(RTOS)的时基选择直接影响系统性能和稳定性。对于使用STM32系列芯片的开发者来说,CubeMX工具极大简化了FreeRTO…...

内存屏障核心解析:从指令重排到 StoreLoad 屏障的本质

多核并发编程中,内存屏障是保证可见性与顺序性的核心。本文将用最通俗的方式拆解四种内存屏障,重点剖析StoreLoad为何是最强且代价最高的屏障,并说明它在Java中的体现。 一、问题背景:CPU为什么会乱序执行? 为了提升指…...

KiCad新手必看:如何将AD原理图库一键转换(含Lua环境配置指南)

KiCad迁移实战:Altium Designer原理图库高效转换全流程指南 从Altium Designer到KiCad的迁移背景 对于长期使用Altium Designer(简称AD)的工程师来说,切换到开源工具KiCad往往面临一个重要挑战:如何将多年积累的元件库…...

AHT20 vs SHT30:低功耗温湿度传感器选型指南与性能对比

AHT20 vs SHT30:低功耗温湿度传感器选型指南与性能对比 在物联网设备、环境监测系统和便携式仪器设计中,温湿度传感器的选型往往直接影响产品的续航能力、数据可靠性和整体成本。面对市场上琳琅满目的传感器型号,工程师们常常陷入选择困境&am…...

提示工程架构师必备的零样本学习实践技巧

提示工程架构师必备的零样本学习实践技巧:让模型“无师自通”的艺术 一、引入与连接:当“未见过的任务”突然降临 凌晨3点,你正在加班处理项目,产品经理发来紧急需求:“我们需要一个能识别‘新能源汽车用户投诉意图’的…...

大数据工程中的隐私计算技术实现

大数据工程中的隐私计算技术实现:从“数据可用不可见”到落地实践 引言:当大数据遇到隐私危机,我们需要“不看数据也能算”的魔法 2022年,某头部出行平台因“未经用户同意收集精准位置信息”被监管部门罚款8000万元;20…...

ChatGPT多模态技术拆解:GPT-4o端到端架构与实测

GPT-4o是OpenAI首个端到端多模态模型,原生支持文本、图像、音频的混合输入与输出,响应速度达到毫秒级。其技术突破在于统一Transformer架构处理多模态数据,大幅降低了视觉-语言任务的延迟。国内用户若想体验GPT-4o的多模态能力,可…...

2026年ChatGPT技术拆解:从架构原理到国内免费使用方案

ChatGPT作为当前大语言模型的代表,其核心技术在于Transformer架构、RLHF(人类反馈强化学习)训练以及大规模算力支撑。对于国内用户而言,想要深入体验并对比不同模型的技术特点,目前最便捷的方案是使用聚合镜像平台RskA…...

Kimmy评论论文的深度分析:AI Agent自我认知与进化路径

Kimmy评论论文的深度分析:AI Agent自我认知与进化路径 引言 最近Kimmy针对某篇AI Agent相关论文发表了重要评论,引发了业内广泛讨论。作为长期从事AI Agent系统设计的实践者,我想从技术实现、理论框架和实际应用三个维度,对Kimmy的…...

保姆级教程:用OpenCV SGBM算法从双目图像生成3D点云(附完整Python代码)

从双目图像到3D点云:OpenCV SGBM算法实战指南 双目视觉技术正逐渐成为计算机视觉领域的重要分支,它通过模拟人类双眼的立体视觉机制,能够从两张不同视角拍摄的图像中恢复出场景的三维信息。本文将带领读者从零开始,使用OpenCV中的…...

用Python模拟完全弹性碰撞:从公式推导到可视化演示(附完整代码)

用Python模拟完全弹性碰撞:从公式推导到可视化演示(附完整代码) 在物理仿真领域,完全弹性碰撞是一个经典的研究课题。它不仅帮助我们理解动量守恒和能量守恒的基本原理,还能通过编程实现直观的可视化效果。本文将带你从…...

[开关电源-拓扑解析] 从伏秒积平衡到设计实战:Buck/Boost/Buck-Boost在CCM模式下的核心公式与应用场景

1. 伏秒积平衡:理解开关电源的黄金法则 第一次接触开关电源设计时,我被各种拓扑结构搞得晕头转向,直到真正理解了伏秒积平衡这个概念,才突然有种豁然开朗的感觉。简单来说,伏秒积平衡就像是给电感"记账"——…...

Windows下Neo4j 4.4社区版安装避坑指南:从环境变量配置到浏览器访问

Windows下Neo4j 4.4社区版安装与实战指南 1. 为什么选择Neo4j作为你的第一个图数据库 在数据爆炸的时代,传统关系型数据库在处理复杂关联数据时显得力不从心。想象一下,当你需要分析社交网络中用户之间的多层关系,或者电商平台中商品与用户…...

DiskGenius实战:误删分区后如何用‘搜索丢失分区‘功能救回数据(附详细步骤)

DiskGenius数据恢复实战:误删分区后的完整救援指南 当你发现硬盘上的某个分区突然消失,或者系统提示"未格式化"时,那种心跳加速的感觉我深有体会。去年帮一位摄影师客户恢复婚礼照片时,亲眼见证了他从绝望到欣喜的全过程…...

基于多控制策略的车辆路径跟踪仿真研究

基于前轮转向转矩分配(AFSDYC)模型预测控制(MPC)路径跟踪(PTC)侧偏角软约束,目前的范例是72km/h,附着系数0.85双移线。 仿真使用的是MATLAB2020b版本和carsim2020。 MPC有两个:第一个为增量式方法编写,采用s-function实现&#xf…...

FLAC3D 钢筋混凝土梁四点弯破坏过程数值模拟

flac3d钢筋混凝土梁四点弯破坏过程数值模拟在土木工程领域,了解钢筋混凝土梁在不同受力状态下的破坏过程至关重要。数值模拟为我们提供了一种深入探究这一过程的有效手段,今天就来聊聊使用 FLAC3D 对钢筋混凝土梁四点弯破坏过程进行数值模拟的那些事儿。…...

51单片机寻迹避障小车的奇妙之旅

51单片机寻迹避障小车(遇障碍物停车)仿真+源程序,两个版本,指示灯或LCD 仿真图设计: (1)寻迹功能的两个红外传感器,用两个单刀开关来模拟(断开为高电平1&…...

基于Matlab实现面和线接触滑块润滑的奇妙之旅

基于matlab的面和线接触的滑块润滑,基于有限差分法求解面接触滑块润滑的油膜厚度、油膜压力,输出三维可视化结果。 程序已调通,可直接运行。最近在研究滑块润滑的问题,今天就来和大家分享一下基于Matlab实现面和线接触滑块润滑分析…...

探索ICEEMDAN - iMPA - BiLSTM在功率/风速预测中的奇妙之旅

ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆网络时间序列预测~组合预测 Matlab语言 1.分解时避免了传统经验模态分解的一些固有缺陷,效果更佳,并通过改进的海洋捕食者算法对BiLSTM四个…...

基于matlab的雾霾天气+夜间车牌识别系统 【车牌识别】基于计算机视觉,数字图像处理常见实战项目

基于matlab的雾霾天气夜间车牌识别系统 【车牌识别】基于计算机视觉,数字图像处理常见实战项目:雾霾天气及夜间车牌识别语音播报GUI显示车牌信息导出。 含GUI界面。 预处理过程:去雾增强算法,亮度增强算法。 车牌处理过程&#xf…...

Yolo免环境训练工具:支持多版本Yolo标注与训练的实用工具集

yolo免环境训练工具 yolo8标注工具 yolo训练工具 yolo8 yolo4 yolo3 yolo无需搭建环境训练工具 免环境标注、训练的工具 支持版本 yolo3 yolo4 yolo8(电脑显卡必须N卡) 可训练模型 cfg weights bin param pt yolo8l.pt yolo8m.pt yolo8n.pt yolo8s.pt yolo8x.pt 实用功能 自动…...

解锁LyricsX高效配置:让你的macOS歌词体验无缝升级

解锁LyricsX高效配置:让你的macOS歌词体验无缝升级 【免费下载链接】LyricsX 🎶 Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的开源歌词工具,能够自动同步显示歌…...

基于Simulink和Carsim的车辆主动悬架防侧翻控制项目报告

车辆主动悬架防侧翻控制 利用Simulink和Carsim进行联合仿真,搭建主动悬架以及防倾杆模型,在不同转角工况下进行仿真试验,设置滑模等控制器计算维持车辆侧倾稳定性所需的力矩,将力矩分配到各个悬架实现控制效果。 控制效果良好&…...

基于同步旋转坐标系的高效无位置传感器永磁同步电机控制策略——采用三相电压重构,告别传统电压采集...

同步旋转坐标系下,无位置传感器永磁同步电机控制,创新点为三相电压为重构,不需要电压采集模块。 需matlab2018a及以上。凌晨三点的实验室里,咖啡机突然罢工。看着示波器上跳动的波形,我突然意识到——电机控制工程师的…...

搞定芯片设计后仿:手把手教你在Linux上为Cadence配置QRC寄生参数提取工具

芯片设计后仿实战:Linux系统下Cadence QRC工具深度配置指南 在芯片设计流程中,后仿真验证环节直接关系到最终流片的成败。寄生参数提取作为连接物理设计与时序验证的关键步骤,其精度和效率直接影响芯片性能分析的可靠性。本文将聚焦Cadence Q…...

麒麟系统v10 SP3上MariaDB的5个隐藏技巧,新手必看!

麒麟系统v10 SP3上MariaDB的5个隐藏技巧,新手必看! 麒麟系统v10 SP3作为国产操作系统的代表,其内置的MariaDB数据库管理系统凭借轻量高效的特点,成为开发者构建本地应用的优选方案。但许多新手用户仅停留在基础操作层面&#xff0…...

AI Agent框架选型:OpenClaw、LangChain、AutoGPT、CrewAI,到底该选哪个?

先说结论Go写命令行AI客户端,核心是HTTP请求JSON处理,代码量不大,但依赖管理、错误处理、上下文维护这些细节才是实际成本。这种方案适合快速验证、个人工具,但生产环境要考虑API成本、速率限制、错误重试、日志监控。如果只是调用…...

告别普通CardView!用MaterialCardView这5个属性,让你的Android应用卡片颜值飙升

解锁MaterialCardView的5个高阶设计属性:让Android卡片交互更优雅 在移动应用界面设计中,卡片(Card)已经成为信息组织和视觉呈现的基础单元。从社交动态到电商商品,从设置项到内容摘要,卡片式布局无处不在。…...