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

JWT 过期后 自动刷新方案

JWT(JSON Web Token)广泛应用于现代 Web 开发中的认证与授权,它以无状态、灵活和高效的特点深受开发者欢迎。然而,JWT 的一个核心问题是 Token 过期后如何处理。本文将总结常见的解决方案,分析其优缺点,并帮助开发者选择适合自己项目的方案。


JWT 过期问题的挑战
  1. 安全性:如果 Token 长时间有效,泄露后可能导致严重的安全问题;短时间有效则需要频繁刷新。
  2. 无状态性:JWT 通常是无状态的,如何在不依赖后端存储的情况下管理过期 Token 成为难点。
  3. 刷新机制:如何设计高效、安全的 Token 刷新机制,避免用户频繁登录体验不佳。

解决方案

方案一:双 Token 模式(Access Token + Refresh Token)
设计思路
  • 使用两个 Token:
    1. Access Token:短生命周期(如 15 分钟)。
    2. Refresh Token:长生命周期(如 7 天)。
  • 客户端使用 Access Token 请求资源;当 Access Token 过期时,使用 Refresh Token 获取新的 Access Token 和 Refresh Token。
优点
  • 高安全性:Access Token 即使泄露,时间窗口较短,风险可控。
  • 客户端和服务器可以协同管理 Refresh Token,有效防止重复使用攻击。
缺点
  • 客户端实现复杂度较高,需要管理两个 Token。
  • 需要额外的接口和逻辑处理 Refresh Token。
适用场景
  • 对安全性要求较高的系统,如金融、支付平台。
核心代码

后端接口验证 Refresh Token 并生成新 Token:

@PostMapping("/refresh-token")
public ResponseEntity<?> refreshToken(@RequestBody Map<String, String> tokens) {String refreshToken = tokens.get("refreshToken");if (!jwtUtil.checkToken(refreshToken)) {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid Refresh Token");}Map<String, String> claims = jwtUtil.decode(refreshToken);String newAccessToken = jwtUtil.generateJwtToken(claims.get("username"), claims.get("userId"));String newRefreshToken = jwtUtil.generateRefreshToken(claims.get("username"), claims.get("userId"));return ResponseEntity.ok(Map.of("accessToken", newAccessToken, "refreshToken", newRefreshToken));
}

方案二:固定 Session ID + Token
设计思路
  • 后端生成唯一的 Session ID 并与 Token 关联,将会话信息(如 Token 状态、用户信息)存储到 Redis 或数据库。
  • 客户端请求时,携带 Session ID 和 Token,后端验证会话状态和 Token。
优点
  • 可灵活控制会话状态,支持主动使某些 Session 失效。
  • 后端可以精细化管理 Token 状态,无需频繁解析 JWT 签名。
缺点
  • 依赖 Redis 或数据库存储会话信息,增加系统复杂度。
  • 不完全无状态,分布式部署时需要额外处理会话同步。
适用场景
  • 用户登录频繁、对会话状态要求高的系统。
核心代码
// 从 Redis 获取会话信息并验证 Token
SessionInfo sessionInfo = redisUtil.get("session_" + sessionId, SessionInfo.class);
if (sessionInfo == null || !sessionInfo.getToken().equals(token)) {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Session Invalid");
}// Token 过期时刷新
if (jwtUtil.isTokenExpired(token)) {String newToken = jwtUtil.generateJwtToken(sessionInfo.getUsername(), sessionInfo.getUserId());sessionInfo.setToken(newToken);redisUtil.set("session_" + sessionId, sessionInfo);return ResponseEntity.ok(Map.of("newToken", newToken));
}

方案三:Token 无状态 + 客户端定时刷新
设计思路
  • Token 完全无状态,仅存储签名信息和过期时间。
  • 客户端定期检查 Token 的有效期,并在即将过期时主动请求刷新。
优点
  • 无需后端存储任何会话信息,完全无状态。
  • 简单高效,适合分布式系统。
缺点
  • 客户端需要管理 Token 刷新逻辑,增加复杂度。
  • 无法主动失效某个用户会话(如强制下线)。
适用场景
  • 轻量级或低安全需求的系统,如小型工具或内部系统。
核心代码

客户端定时检查并刷新:

function checkTokenExpiry() {const token = localStorage.getItem('accessToken');const payload = JSON.parse(atob(token.split('.')[1]));const expiryTime = payload.exp * 1000;if (Date.now() > expiryTime - 5 * 60 * 1000) { // 提前 5 分钟刷新refreshToken();}
}function refreshToken() {const refreshToken = localStorage.getItem('refreshToken');fetch('/refresh-token', {method: 'POST',body: JSON.stringify({ refreshToken }),headers: { 'Content-Type': 'application/json' }}).then(response => response.json()).then(data => {localStorage.setItem('accessToken', data.accessToken);localStorage.setItem('refreshToken', data.refreshToken);});
}

方案四:Hybrid Token(混合 Token)
设计思路
  • 将部分会话信息存储到 Token 中,而状态信息(如是否过期)存储在 Redis。
  • Token 验证时仅检查无状态部分,必要时从 Redis 获取状态信息。
优点
  • 兼顾无状态性和灵活性。
  • 后端可动态管理会话状态,同时减少频繁访问存储。
缺点
  • 实现较复杂,适合对性能要求较高的场景。
适用场景
  • 高并发、大规模分布式系统,如社交平台、内容分发系统。

方案对比

方案优点缺点适用场景
双 Token 模式高安全性;支持长生命周期管理增加客户端复杂度金融、支付等高安全系统
Session ID + Token灵活控制会话状态,支持主动失效依赖 Redis 或数据库存储登录频繁的系统
无状态 Token完全无状态,简单高效客户端复杂度高,无法主动失效内部工具、轻量级系统
Hybrid Token兼顾性能和灵活性实现复杂高并发分布式系统

结语

不同的方案适用于不同的场景,开发者在选择方案时需要考虑:

  1. 安全性:是否需要强安全性保障,如支持主动失效。
  2. 性能:是否需要减少后端存储依赖或高效处理。
  3. 复杂度:是否愿意增加客户端和后端的实现复杂性。

在实际开发中,可以结合业务需求和技术条件选择最适合的方案,甚至进行多方案组合,实现性能与安全的平衡。

相关文章:

JWT 过期后 自动刷新方案

JWT&#xff08;JSON Web Token&#xff09;广泛应用于现代 Web 开发中的认证与授权&#xff0c;它以无状态、灵活和高效的特点深受开发者欢迎。然而&#xff0c;JWT 的一个核心问题是 Token 过期后如何处理。本文将总结常见的解决方案&#xff0c;分析其优缺点&#xff0c;并帮…...

react-amap海量点优化

前言&#xff1a;高版本的react-amap 支持MassMarkers 组件用于一次性添加大量的标记点。本次优化的海量点是在低版本react-amap的基础上。官方推荐使用聚合useCluster属性来优化海量点的渲染。 直接附上代码&#xff1a; import React, { Component } from "react"…...

GRU(门控循环单元)详解

1️⃣ GRU介绍 前面介绍的LSTM可以有效缓解RNN的梯度消失问题&#xff0c;但是其内部结构比较复杂&#xff0c;因此衍生出了更加简化的GRU。GRU把输入门和遗忘门整合成一个更新门&#xff0c;并且合并了细胞状态和隐藏状态。于2014年被提出 2️⃣ 原理介绍 GRU的结构和最简单…...

【代码随想录|回溯算法排列问题】

491.非减子序列 题目链接. - 力扣&#xff08;LeetCode&#xff09; 这里和子集问题||很像&#xff0c;但是这里要的是非递减的子序列&#xff0c;要按照给的数组的顺序来进行排序&#xff0c;就是如果我给定的数组是[4,4,3,2,1]&#xff0c;如果用子集||的做法先进行排序得到…...

Azure Kubernetes Service (AKS)资源优化策略

针对Azure Kubernetes Service (AKS)的资源优化策略&#xff0c;可以从多个维度进行考虑和实施&#xff0c;以提升集群的性能、效率和资源利用率。以下是一些关键的优化策略&#xff1a; 一、 Pod资源请求和限制 设置Pod请求和限制&#xff1a;在YAML清单中为所有Pod设置CPU和…...

R语言 | 宽数据变成一列,保留对应的行名和列名

对应稀疏矩阵 转为 宽数据框&#xff0c;见 数据格式转换 | 稀疏矩阵3列还原为原始矩阵/数据框&#xff0c;自定义函数 df3toMatrix() 目的&#xff1a;比如查看鸢尾花整体的指标分布&#xff0c;4个指标分开&#xff0c;画到一个图中。每个品种画一个图。 1.数据整理&#…...

RTSP播放器EasyPlayer.js播放器在webview环境下,PC和安卓能够正常播放,IOS环境下播放器会黑屏无法播放

流媒体技术分为顺序流式传输和实时流式传输两种。顺序流式传输允许用户在下载的同时观看&#xff0c;而实时流式传输则允许用户实时观看内容。 流媒体播放器负责解码和呈现内容&#xff0c;常见的播放器包括VLC和HTML5播放器等。流媒体技术的应用场景广泛&#xff0c;包括娱乐…...

.NET周刊【11月第3期 2024-11-17】

国内文章 .NET 9使用Scalar替代Swagger https://www.cnblogs.com/netry/p/18543378/scalar-an-alternative-to-swagger-in-dotnet-9 .NET 9 移除了 Swashbuckle.AspNetCore&#xff0c;因为其维护不力&#xff0c;并转向 Microsoft.AspNetCore.OpenApi。除了 Swashbuckle&am…...

c语言数据22数组使用

1.1数组分配的空间 int a[10]{1,2,3,4,5,6,7,8,9,10};//分配空间 元素类型大小int4*元素个数1040byte 元素之间空间连续 数组名代表数组首元素地址&#xff1b;a 取的是a[0]的地址&#xff1b;&a 是整个数组的地址 说明&#xff1a; 数组首元素地址&#xff1a; 0号元…...

深入理解TensorFlow中的形状处理函数

摘要 在深度学习模型的构建过程中&#xff0c;张量&#xff08;Tensor&#xff09;的形状管理是一项至关重要的任务。特别是在使用TensorFlow等框架时&#xff0c;确保张量的形状符合预期是保证模型正确运行的基础。本文将详细介绍几个常用的形状处理函数&#xff0c;包括get_…...

MySQL数据库3——函数与约束

一.函数 1.字符串函数 MySQL中内置了很多字符串函数&#xff0c;常用的几个如下&#xff1a; 使用方法&#xff1a; SELECT 函数名(参数);注意&#xff1a;MySQL中的索引值即下标都是从1开始的。 2.数值函数 常见的数值函数如下&#xff1a; 使用方法&#xff1a; SELECT…...

⾃动化运维利器 Ansible-Jinja2

Ansible-Jinja2 一、Ansible Jinja2模板背景介绍二、 JinJa2 模板2.1 JinJa2 是什么2.2 JinJa2逻辑控制 三、如何使用模板四、实例演示 按顺序食用&#xff0c;口味更佳 ( 1 ) ⾃动化运维利器Ansible-基础 ( 2 ) ⾃动化运维利器 Ansible-Playbook ( 3 ) ⾃动化运维利器 Ansible…...

博客文章怎么设计分类与标签

首发地址&#xff08;欢迎大家访问&#xff09;&#xff1a;博客文章怎么设计分类与标签 新网站基本上算是迁移完了&#xff0c;迁移之后在写文章的过程中&#xff0c;发现个人的文章分类和标签做的太混乱了&#xff0c;分类做的像标签&#xff0c;标签也不是特别的丰富&#x…...

FastDDS之DataSharing

目录 原理说明限制条件配置Data-Sharing delivery kindData-sharing domain identifiers最大domain identifiers数量共享内存目录 DataReader和DataWriter的history耦合DataAck阻塞复用 本文详细记录Fast DDS中Data Sharing的实现原理和代码分析。 DataSharing的概念&#xff1…...

计算机网络在线测试-概述

单项选择题 第1题 数据通信中&#xff0c;数据传输速率&#xff08;比特率&#xff0c;bps&#xff09;是指每秒钟发送的&#xff08;&#xff09;。 二进制位数 &#xff08;我的答案&#xff09; 符号数 字节数 码元数 第2题 一座大楼内的一个计算机网络系统&#xf…...

【MySQL】数据库必考知识点:查询操作全面详解与深度解剖

前言&#xff1a;本节内容讲述基本查询&#xff0c; 基本查询要分为两篇文章进行讲解。 本篇文章主要讲解的是表内删除数据、查询结果进行插入、聚合统计、分组聚合统计。 如果想要学习对应知识的可以观看哦。 ps:本篇内容友友们只要会创建表了就可以看起来了哦&#xff01;&am…...

鲸鱼机器人和乐高机器人的比较

鲸鱼机器人和乐高机器人各有其独特的优势和特点&#xff0c;家长在选择时可以根据孩子的年龄、兴趣、经济能力等因素进行综合考虑&#xff0c;选择最适合孩子的教育机器人产品。 优势 鲸鱼机器人 1&#xff09;价格亲民&#xff1a;鲸鱼机器人的产品价格相对乐高更为亲民&…...

游戏引擎学习第15天

视频参考:https://www.bilibili.com/video/BV1mbUBY7E24 关于游戏中文件输入输出&#xff08;IO&#xff09;操作的讨论。主要分为两类&#xff1a; 只读资产的加载 这部分主要涉及游戏中用于展示和运行的只读资源&#xff0c;例如音乐、音效、美术资源&#xff08;如 3D 模型和…...

详解模版类pair

目录 一、pair简介 二、 pair的创建 三、pair的赋值 四、pair的排序 &#xff08;1&#xff09;用sort默认排序 &#xff08;2&#xff09;用sort中的自定义排序进行排序 五、pair的交换操作 一、pair简介 pair是一个模版类&#xff0c;可以存储两个值的键值对.first以…...

AI驱动的桌面笔记应用Reor

网友 竹林风 说&#xff0c;已经成功的用 mxbai-embed-large 映射到 text-embedding-ada-002&#xff0c;并测试成功了。不愧是爱折腾的人&#xff0c;老苏还没时间试&#xff0c;因为又找到了另一个支持 AI 的桌面版笔记 Reor Reor 简介 什么是 Reor ? Reor 是一款由人工智…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...