关于refresh_token
前文介绍过jwt的一般使用场景,用户登录成功后获得jwt,其中包含用户相关信息,主要是在前端要用到的属性(比如姓名、应用角色[这个前端后都用得着]等)、在后端要用到的属性(比如登录IP、终端唯一标识)、token过期时间(这个前后端都可以检查),之后调用后端服务都会在header里带上jwt,具体就是Authorization属性的值设置为’Bearer ’ + jwt。这样后端收到请求后,会对jwt进行验签和解析,如果签名正确,且在有效期内,则认可jwt解析出来的用户身份,进行相关后续处理,否则跳转登录界面重新登录。
出于安全考虑,再加上用户身份权限也不是一成不变的,所以一般token有效期不应设置过长,比如一个小时?其实不论多长时间,总会有超期时间,这时候用户访问时会跳转到登录界面要求重新登录,这样的体验是不太好的,所以一般情况下,登录成功后,可以提供两个token给前端,一个是access_token,也就是前面介绍的通常意义上的jwt,而另一个是refresh_token,它的有效期比access_token的要长一些,用户在access_token过期且access_token未过期情况下可为前端重新申请access_token(其实也可以同时更新refresh_token)
我们可以将refresh_token放在access_token的属性中,这样每次access_token传到后端时,refresh_token也自然一起传了过来,在后端主动推送token的场景下要求前端每次请求都传两个token的。前端主动申请刷新token的场景下,refresh_token就没有必要每次传,只要在刷新时传就可以了,也就没有必要将refresh_token放在access_token的属性中。
其实有两种方式来执行token的更新,一种是利用了后端主动访问前端的SSE或者websocket方式,后端解析请求发现access_token过期且refresh_token未过期,可以主动从SSE或websocket通道连接前端,推送新的access_token和refresh_token到前端,前端收到token更新后存入本地存储,并在每次发起后端请求时放在header相关属性中一并发出。不过这种方式由于要维护前端通信通道,有违http服务无状态的初衷,虽然可以实现,不过不推荐。
另外一种是在前端axios里配置拦截器,可以配置请求拦截或者响应拦截。区别如下:请求拦截的话,每次发起请求前检查access_token是否超期,如果没有,直接发起原请求,否则检查refresh_token是否超期,如果超期,则跳转登录界面,还在有效期的话,可以发起刷新token的调用更新token。返回后写入token到本地,然后放在header里发起原请求,另外由于很难要求前后端时间严格同步,所以建议在access_token到期前一段时间内(比如一分钟)就请求刷新。响应拦截的话,请求后根据服务器响应再做后续处理,如果响应正常,则原响应返回,如果提示token超期的话,要执行刷新token,返回后写入token到本地,然后放在header里发起原请求。两种拦截器效果区别不大,不过按javascript风格——先操作再处理error——的话,是倾向于响应拦截器的。
这里还有一个小问题,就是在本地存储的token过期,而新的token尚未返回写入本地存储时,可能发起了多个请求,如果后端每次都新生成token就没有必要了,后端可以考虑维护一个列表,存有新生成的token、有效期与前端ip或者唯一标识,这样只要在列表中找到就不用重新生成,直接分配即可。此时前端处理会比较简单,会发起多次申请和写入,不过写入的是同样的内容,其实也没有啥不太好的影响,主要是多次申请token和写回本地存储有些前后端的多余的不必要的开销。改进的方式是在前端设置一个变量来标识是否处于刷新token中,这样第一个刷新会向后端提交申请,而其余的返回token过期的申请或者新的请求申请要暂时挂起放入队列不提交,等待这第一个刷新完成后,队列里申请再激活提交。示例代码如下,主要逻辑在响应拦截器里处理,配置请求拦截器是为了处理刷新token期间的请求挂起,并在刷新到token后恢复。
var inRefresh = false;
var reqlist = [];const instance = axios.create();
instance.interceptors.request.use(config=>{if (!inRefresh) return config;return new Promise(resolve => {reqlist.push(token=>{config.headers.Authorization = "Bearer "+token;resolve(config);})})
});instance.interceptors.response.use( response => { return response }, error => {if (error.response.status == 401) {let config = error.config;if (!inRefresh) {inRefresh = true;axios.post("/app/refresh_token",{"refresh_token":localStorage.getItem('refresh_token')}).then(res=>{let jwt=res.data.access_token;config.defaults.headers.common['Authorization'] = "Bearer " + jwt;localStorage.setItem("jwt", jwt);localStorage.setItem("refresh_token", res.data.refresh_token);reqlist.forEach((cb) => cb(jwt));reqlist = [];return instance(config);}).catch(err => { return Promise.reject(err) }).finally(() => { inRefresh = false })}else {return new Promise(resolve => {reqlist.push(token => {config.headers.Authorization = "Bearer "+token;resolve(instance(config));})})}}else return Promise.reject(error)
})
相关文章:
关于refresh_token
前文介绍过jwt的一般使用场景,用户登录成功后获得jwt,其中包含用户相关信息,主要是在前端要用到的属性(比如姓名、应用角色[这个前端后都用得着]等)、在后端要用到的属性(比如登录IP、终端唯一标识…...

Linux网络:基于OS的网络架构
Linux网络:OS视角下的网络架构 网络分层模型OSI 七层模型TCP/IP 五层模型 协议操作系统与网络网络相关命令ifconfigpingnetstat 本博客将基于操作系统,讲解计算机网络的设计理念,帮助大家理解操作系统与网络之间的关系。 网络分层模型 网络…...

UEC++学习(十六)变量添加中文注释、ui设置中文文本
(一)变量添加中文注释 在C 项目中创建变量,并在蓝图中显示变量的英文名同时附带中文注释,可以使用UPROPERTY 的 ToolTip 元数据属性来实现 UPROPERTY(EditAnywhere, meta (ToolTip "弹夹最大容量"))int32 MagCapacit…...
Redis延迟双删
1、何为延时双删 Redis延迟双删是一种在数据更新操作中确保缓存与数据库数据一致性的策略,通过两次缓存删除操作间隔一段延时来减少数据不一致的问题。 在并发环境下,多个请求同时对同一数据进行读写时,如果没有妥善处理,很容易…...

WO Mic 手机变身免费麦克风
目录 一、主要特点 1.支持多种连接方式 2.应用广泛 3.低延迟 4.简易配置 5.自动连接 6.音频格式 二、软件下载 三、软件安装 四、系统连接 五、测试 直播的时候,上课的时候,会议的时候……突然发现没有麦克风或者电脑麦克风有故障,这可怎么办呢?今天给大家介绍一…...

MQ死信对列
面试题:你们是如何保证消息不丢失的? 1、什么是死信 死信就是消息在特定场景下的一种表现形式,这些场景包括: 1. 消息被拒绝访问,即消费者返回 basicNack 的信号时 或者拒绝basicReject 2. 消费者发生异常࿰…...

springboot乡镇小区管理系统-计算机毕业设计源码73685
摘 要 过去使用手工的管理方式对乡镇小区进行管理,造成了管理繁琐、难以维护等问题,如今使用计算机对停车场停车的各项基本信息进行管理,比起手工管理来说既方便又简单,而且具有易于管理、搜索速度快、存储量大等多个优点。将其使…...

基于vue框架的4S店汽车维修保养管理系统28a7y(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
系统程序文件列表 项目功能:客户,技师,车辆信息,财务,客户维修,维修分配,维修订单,保养预约,保养分配,保养订单,维修费用,保养费用 开题报告内容 基于Vue框架的4S店汽车维修保养管理系统 开题报告 一、项目背景与意义 随着汽车产业的迅猛发展,4S店作…...

小米开放式耳机值得买吗?南卡、小米、漫步者一周横评
大家好,最近对开放式耳机比较感兴趣,作为一名数码博主以及多年的耳机发烧友,今天想给大家测评一下开放式耳机,这类耳机目前在数码圈非常火热!很多喜欢运动的小伙伴都选择了这款耳机,搭配运动场景听歌&…...
解决oracel锁表问题;SQL 错误 [54] [61000]: ORA-00054: 资源正忙
问题描述; SQL 错误 [54] [61000]: ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 select session_id from v$locked_object;查看这些 session_id 对应的会话的详细信息,包括用户名、机器名、程序等,9596等是select se…...
Jfinal与hibernate-validator实现后台表单
一. pom.xml配置 jfianl maven项目基础上增加 <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>${hibernate-validator.version}</version></dependency><dependency…...
ansible playbook使用jinja2语法渲染inventory下的主机名和IP到/etc/hosts
1. ansible inventory 下面的 hosts内容如下: [all_host] app1 ansible_host10.2.162.147 app2 ansible_host10.2.162.148 app3 ansible_host10.2.162.149 app4 ansible_host10.2.162.150 app5 ansible_host10.2.162.151[nginx] app12. hosts.j2内容如下 127.0.0…...

张飞硬件1~9电阻篇笔记
电阻有标定值和实际值,关于误差的问题: 精密的电流、电压采样可能会用到1%的精度。如果只是做限流用途的话,用5%就足够。 电阻功率:标定值、额定值、瞬态值: 标定值由封装所决定,例如5W额定值由电路中平…...
探索Golang的微观世界:用net/trace包追踪网络操作
标题:探索Golang的微观世界:用net/trace包追踪网络操作 在Go语言的丰富生态系统中,net/trace包是一个强大的工具,它允许开发者深入网络请求的微观世界,洞察每一次数据的流动和操作的执行。本文将详细探讨如何使用net/…...

Unity开发抖音小游戏广告部分接入
Unity开发抖音小游戏广告部分接入 介绍环境确保开通流量主获取广告位广告部分代码测试如下总结 介绍 最近在使用Unity做抖音小游戏这块的内容,因为要接入广告,所以这里我把我接入广告的部分代码和经验分享一下。 环境确保 根据抖音官方的文档我们是先…...

World of Warcraft [CLASSIC] 80 WLK [Gundrak] BUG
World of Warcraft [CLASSIC] 80 WLK [Gundrak] BUG 魔兽世界怀旧版,80级,5人副本古达克,科技队伍(BUG队伍) 副本有两个门口 这样看,是不是觉得很怪。是的,和图1刚好相反的。 因此应该翻转180…...

极狐GitLab 密钥推送保护如何保护密钥信息被泄露?
极狐GitLab 是 GitLab 在中国的发行版,专门面向中国程序员和企业提供企业级一体化 DevOps 平台,用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规,而且所有的操作都是在一个平台上进行,省事省心省钱。可以一键安装极狐GitL…...

Qt+TSC打印机调试
前言 最近被TSC打印机整的死去活来,记录一下使用方法。 一、环境 Qt5.15.2 mingw tsc TE244 二、使用步骤 1.引入库 从官网下载windows C SDK,引入库,以下是.pro文件 QT core gui printsupportgreaterThan(QT_MAJOR_VERSION, 4)…...

QT 添加程序图标
1. 使用免费网站将其他图片格式转化成ico格式 Ico转换器 : https://cn.free-converter.com/ico-converter 2.qmake项目添加程序图标 在.pro文件内添加语句,如下图 RC_ICONS favicon.ico2.1 程序图标文件添加到项目目录内 2.2 通过windeployqt xxx.exe构建生成的…...

数据结构与算法 - 贪心算法
一、贪心例子 贪心算法或贪婪算法的核心思想是: 1. 将寻找最优解的问题分为若干个步骤 2. 每一步骤都采用贪心原则,选取当前最优解 3. 因为没有考虑所有可能,局部最优的堆叠不一定让最终解最优 贪心算法是一种在每一步选择中都采取在当前…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...