如何做到无感刷新Token?

关于实现token无感刷新的解决方案 问题引入 在开发中为了安全或满足分布式场景,通常会舍弃原有的session认证手段,而采用jwt(json web token);但是使用token难免遇到token有效期的问题,如果token长期有效,服务端不断发布新的token,导致有效的token越来越多,这必然是存在安全问题的。而token不想session一样,在用户操作时会进行刷新,为了用户体验,这个刷新就需要自己实现。 方案 一、使用旧token获取新token 如果采取单个token的方式要实现token的自动刷新,就必须使用定时器,每隔一 阅读详情
全新前后端微商城项目,手把手教学!
全新前后端微商城项目,手把手教学!
全新前后端微商城项目,手把手教学!

来源:juejin.cn/post/7316797749517631515

为什么需要无感刷新Token?

  • 「最近浏览到一个文章里面的提问,是这样的:」

    当我在系统页面上做业务操作的时候会出现突然闪退的情况,然后跳转到登录页面需要重新登录系统,系统使用了Redis做缓存来存储用户ID,和用户的token信息,这是什么问题呢?

  • 「解答:」

    突然闪退,一般都是由于你的token过期的问题,导致身份失效。

  • 「解决方案:」

    自动刷新token

    token续约

  • 「思路」

    如果Token即将过期,你在验证用户权限的同时,为用户生成一个新的Token并返回给客户端,客户端需要更新本地存储的Token,

    还可以做定时任务来刷新Token,可以不生成新的Token,在快过期的时候,直接给Token增加时间

自动刷新token

自动刷新token是属于后端的解决方案,由后端来检查一个Token的过期时间是否快要过期了,如果快要过期了,就往请求头中重新

放一个token,然后前端那边做拦截,拿到请求头里面的新的token,如果这个新的token和老的token不一致,直接将本地的token更换

接下来拿代码举例子

  • 先引入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.33</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
  • 这是一个生成token的例子

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

public class JwtUtil {
    // 有效期为
    public static final Long JWT_TTL = 60 * 60 * 1000 * 24;// 60 * 60 * 1000 * 24  一个小时
    // 设置秘钥明文 --- 自己改就行
    public static final String JWT_KEY = "qx";
   // 用于生成uuid,用来标识唯一
    public static String getUUID(){
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");//token用UUID来代替
        return uuid;
    }

    /**
        id      : 标识唯一
        subject : 我们想要加密存储的数据
        ttl     : 我们想要设置的过期时间
     */

   // 生成token  jwt加密 subject token中要存放的数据(json格式)
    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间
        return builder.compact();
    }

    // 生成token  jwt加密
    public static String createJWT(String subject, Long ttlMillis) {
        JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间
        return builder.compact();
    }
  
    // 创建token jwt加密
    public static String createJWT(String id, String subject, Long ttlMillis) {
        JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if(ttlMillis==null){
            ttlMillis=JwtUtil.JWT_TTL;
        }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)              //唯一的ID
                .setSubject(subject)   // 主题  可以是JSON数据
                .setIssuer("sg")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
                .setExpiration(expDate);
    }
    
    // 生成加密后的秘钥 secretKey
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    // jwt解密
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }
}
  • 写个单元测试,测试一下

@Test
void test() throws Exception {
    String token = JwtUtil.createJWT("1735209949551763457");
    System.out.println("Token: " + token);
    Date tokenExpirationDate = getTokenExpirationDate(token);
    System.out.println(tokenExpirationDate);
    System.out.println(tokenExpirationDate.toString());
    long exp = tokenExpirationDate.getTime();
    long cur = System.currentTimeMillis();
    System.out.println(exp);
    System.out.println(cur);
    System.out.println(exp - cur);
}
// 解析令牌并获取过期时间
public static Date getTokenExpirationDate(String token) {
    try {
        SecretKey secretKey = generalKey();
        Claims claims = Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody();
        return claims.getExpiration();
    } catch (ExpiredJwtException | SignatureException e) {
        throw new RuntimeException("Invalid token", e);
    }
}

Token有点长,就不放全部了

c4c54e4a4e4c2bd2b0edbc835ce30a8d.jpeg

可以看到我们的 exp 过期时间的毫秒数为 1703651262000

可以看到我们的 cur 当前时间的毫秒数为 1703564863035

我们将两者相减得到的值为 86398965ms,我们可以算一下一天的毫秒数是多少 1000 * 60 * 60 * 24 ms = 86400000ms

这样我们就能够拿到token的过期时间tokenExpirationDate了

我们就可以通过在校验token的时候,如果token校验通过了,此时我们拿到该token的过期时间,以(过期时间 - 当前时间)进行判断

如果说 (过期时间 - 当前时间) 小于约定的值,那么我们就重新根据token里面的信息,重新创建一个token,将新的token放到请求头中

返回给前端,前端去进行本地存储更新token

前端token续约

token的续约偏向于前端的解决方案,即由前端来进行token的过期时间的判断,首先前后端需要对接商量好一个token续约的接口,

当前端发现这个token快要过期的时候,向后端发送该token,然后后端将该token的过期时间延长。

「前端采用的是双Token的方式,access-token 和 refresh-token即 AT 和 RT」

「而对于纯后端的方式,就是只有access-token这一个token」

  • 「那么问题来了 AT 和 RT 到底有什么区别?为什么需要RT?」

    「在前端实现方案来说,RT是用来在AT即将过期的时候,用RT获取最新的token」

    我解释一下我的观点:

    AT的暴露机会更多,每个请求都要携带,所以设置的过期时间短一点,「减少劫持风险」

    RT只会暴露在auth服务中用来刷新at,设置的过期时间长一点,「增加便利性。」

    AT 和 RT 是为了网络传输安全,网络传输中,容易暴露 AT,因为 AT 时间短,暴露后风险系数才低

    「这种是标准的安全处理,其实已经无需探讨他的合理性,就好像 https 之于 http 一样」

疑问及思考

要是前端有一个表单页面,长时间不进行请求的发送,此时用户填写完表单了,再点击提交的时候,后端返回401了,怎么办?

也就是说,虽然你后端可以无感刷新Token,但是你后端无感刷新Token的前提是:前端得发请求,如果用户长时间不进行页面的交互,

即没有进行任何业务逻辑的跳转什么的,就单纯的往表单上面填东西,什么请求也没发的情况下,后端是无法感知Token过期的

「这种情况怎么解决?」

  • 对于纯后端的解决方案,我是这样想的

    让前端在表单填写内容的时候做处理,如果提交返回的是401,那么前端就需要获取表单存在本地存储 然后跳转登录页,登录成功后

    返回这个页面,然后从本地存储取出来再回显到表单上面。

  • 对于前端的解决方案,我是这样想的

    对于后端来说就是AT过期了,而对于前端来说就是AT和RT都过期了,怎么处理?

  1. 需要监听refresh token的过期时间,在接近过期的时候向后端发起请求来刷新refresh token 或者是定期刷新一下refresh token

  2. 和后端的解决方案一样,前端做一个类似草稿箱的功能对表单等元素进行保存

关于无状态的 JWT 到底应该怎样用?参见:https://t.zsxq.com/15xye5IWG。

推荐全新学习项目
全新基于springboot+vue+vant的前后端分离的微商城项目,包括手机端微商城项目和后台管理系统,整个电商购物流程已经能流畅支持,涵盖商品浏览、搜索、商品评论、商品规格选择、加入购物车、立即购买、下单、订单支付、后台发货、退货等。功能强大,主流技术栈,非常值得学习。
线上演示:https://www.markerhub.com/vueshop

从文档到视频、接口调试、学习看板等方面,让项目学习更加容易,内容更加沉淀。全套视频教程约35小时,共222期,讲解非常详细细腻。下面详细为大家介绍:
架构与业务使用主流的技术架构,真正手把手教你从0到1如何搭建项目手脚架、项目架构分析、建表逻辑、业务分析、实现等。涵盖SpringBoot、Mybatis Plus、Jwt、Redis、Lombok、Hutool、Shiro、Elasticsearch、RabbitMq、Docker、Jenkins等技术。
vueshop微商城的整个购物流程已经完善,各个模块的业务都是已经实现,涵盖商品模块、搜索模块、购物车模块、订单模块、退款模块、后台权限模块、业务数据管理模块等

更多详情请查看:
手把手教学,从0开发前后端微商城项目,主流Java技术一网打尽!

手把手教学,从0开发前后端微商城项目,主流Java技术一网打尽!

手把手教学,从0开发前后端微商城项目,主流Java技术一网打尽!
无感刷新 token 又因为无论是 access token 还是 refresh token 都是放在请求头的 authorization 上携带,此时请求拦截设置的 access token 就会覆盖掉 refresh token,导致刷新接口拿不到 refresh token。前一个刷新请求还没拿到最新的 access token,后一个刷新请求又发出了,这就出现了并发刷新 token ,冗余发送请求的情况。在请求拦截器中保存当前请求的url到数组中,后续的请求都需要判断一下,当前请求的url是否已经在数组中。 阅读详情

相关推荐

Token已过期,我是如何实现无感刷新Token的?

无感刷新Token这个功能,用户成功的时候,是感知不到它的存在的。但恰恰是这种无感的细节,区分出了一个能用的应用和一个好用的应用。因为一个资深的开发者,他不仅关心功能的实现,更应该关心用户体验和整个系统的健壮性。希望这一套解决思路,能对你有所帮助🤞😁。在实际项目中,你可能还需要根据具体的业务场景进行调整,比如添加重试次数限制、更完善的错误处理等。但核心的思路和实现方式都是相通的。掌握了这个技术,你就能让用户在使用你的产品时,再也不用担心因为Token过期而被迫中断操作了!

我爱娃哈哈的专栏 1820

token无感刷新

由后端返回一个过期时间,前端在每次请求时,判断token的过期时间,如果快到过期时间了,就去调用刷新token的接口(不推荐 --- 如果本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败,不建议采用)服务端把用户信息放入 token 里,设置一个过期时间,客户端请求的时候通过 authorization 的 header 携带 token,服务端验证通过,就可以从中取到用户信息。token无感刷新,是为了解决频繁登录造成的用户体验问题,需要前端定时去刷新token,以帮助用户静默登录。

zjy_yue的博客 2727

uniapp无感刷新token实现过程

可以看到已经触发了刷新token接口,并且重新请求上次失败的列表接口,无感刷新token逻辑已经正常,但为什么列表接口请求成功,还一直loading没关闭捏,就是因为后续代码未执行,await接口的返回没有成功resolve。路漫漫其修远兮,前端道路逐渐迷茫,时隔好久好久终于想起了我还有一个小博客,最近在一直在弄uniapp,属实有被恶心到,但也至少会用了,最近实现了一个比较通用的功能,就是无感刷新token,但在过程中发现一个问题就是。3、排查await的列表接口为何没有成功resolve。

weixin_40618068的博客 3595

双token的无感刷新

作为计算机术语时,是“令牌”的意思。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

2301_81801630的博客 2417

实现无感刷新token

登录页面: methods:{ submitLogin:function () { this.$http.post("/auth/loginUser/login",this.formParams).then(res=>{ var ajaxResult = res.data; if(ajaxResult.success){ var accessToken = ajaxResult.result.

weixin_56310628的博客 666

VSCode玩转STM32:手把手教你配置EIDE插件与OpenOCD调试(附野火DAP配置文件详解)

本文详细介绍了如何在VSCode中配置EIDE插件与OpenOCD进行STM32开发,特别针对野火DAP调试器提供了配置文件详解。从基础环境搭建到深度调试技巧,帮助开发者高效完成STM32项目开发,实现现代化嵌入式开发工作流。

weixin_26905487的博客 553

Vue 无感刷新token

Vue 无感刷新token,刷新token的解决方案

前端菜鸟好先森的博客 6153

告别迷茫!手把手教你用Altova XMLSpy编写EtherCAT从站ESI文件(附避坑指南)

本文详细介绍了如何使用Altova XMLSpy高效编写EtherCAT从站ESI文件,涵盖核心架构、通信通道配置、过程数据映射等关键步骤,并提供了常见问题排查与性能优化建议。通过实战案例和避坑指南,帮助工程师快速掌握EtherCAT从站开发技巧,提升工作效率。

weixin_42570484的博客 396

实现Token无感刷新

通过 Axios 的请求拦截器和响应拦截器,可以实现 Token 的无感刷新,从而提升用户体验。关键在于:在 Token 过期前主动刷新。处理并发请求和错误情况。确保 Token 存储和传输的安全性。这种方法适用于大多数前后端分离的项目,能够有效减少用户因 Token 过期而需要重新登录的情况。

qq_43284411的博客 2056

11、iOS设备逻辑数据分析全解析

本文深入解析iOS设备中的逻辑数据,涵盖图像相关数据库(Photos.sqlite和PhotosAux.sqlite)、录音文件、iPhoto照片存储结构、多媒体文件、第三方应用程序、社交网络应用(如Twitter、Skype、Facebook等)以及苹果相关应用(如Google Mobile、Bing)的数据存储结构和取证方法。此外,还介绍了文档类应用(如Pages、Numbers、Documents To Go)的文件存储结构及恢复方法。适用于iOS取证、数据挖掘和数字调查领域。

rain6的博客 226

GIS常用符号化色带(超级色带)根据python制作

GIS自带的色带比较单一,今天分享一款色带,应用之后大家出图的时候可以选择更多的配色,符号化/点击色块/样式引用/将样式添加至列表即可。色带类型比较多,大家可以自己尝试下不同的风格。简单符号化一下,看看效果。以中国县级行政区划为例,

J_Giser的博客 2640

双token无感刷新

双token无感刷新是一种在Web开发中常用的安全及用户体验优化技术,主要涉及到两种类型的token:Access Token(访问令牌)和Refresh Token(刷新令牌)。以下是对双token无感刷新的详细解释

stc_ljc的博客 2630

python基础知识补充

1. jupyter notebook 解释 2. ipython 魔法命令 3. latex in Markdown cell(在markdown里面编写数学公式) 4. jupyter notebook功能扩展:安装Nbextension 5. python解释与运行 6. 垃圾回收(计数机制与分代回收机制) 7. 名字空间与局部作用域L和全局作用域G 8. 小整数缓存区与字符驻留 9. Statement &Expression 10. 调试

weixin_43178406的博客 1万+

双Token实现无感刷新

服务端把用户信息放入token里,设置一个过期时间,客户端请求的时候通过的header携带token,服务端验证通过,就可以从中取到用户信息。token是有过期时间的,比如3天,那过期后再访问就需要重新登录了。这样体验并不好。想想你在用某个app的时候,用着用着突然跳到登录页了,告诉你需要重新登录了。是不是体验很差?所以要加上续签机制,也就是延长token过期时间。主流的方案是通过双token,一个、一个。登录成功之后,返回这两个token访问接口时带上访问:当过期时,通过来刷新,拿到新的。

New_user_的博客 3406

基于RK3588调试WiFi模块AIC8800

本文介绍了在RK3588平台上移植AIC8800 WiFi模块驱动的过程。开发环境基于Linux 6.1内核和Buildroot文件系统。驱动移植步骤包括:将驱动包放入SDK指定目录、修改Makefile、编译内核、放置固件文件、手动加载驱动模块等。文章还分析了两种常见异常情况:无法识别模块(检查USB信号线路和供电)和偶发断连(检查硬件连接和调整PHY寄存器)。成功加载后可通过ifconfig看到wlan0节点。

qq_45147279的博客 667

Django框架中settings文件的部署建议

为了更好地管理开发和生产环境的配置,建议将settings文件分为多个文件,分别用于不同的环境。然后,通过在启动应用程序时指定不同的settings文件,来加载相应的配置。在Django框架中,settings.py文件是非常重要的配置文件,它包含了项目的各种设置和选项。在Django框架中,settings.py文件是非常重要的配置文件,它包含了项目的各种设置和选项。可以使用Python的。为了更好地管理开发和生产环境的配置,建议将settings文件分为多个文件,分别用于不同的环境。

WELL_CODER的博客 129

token 无感刷新

什么是 token 无感刷新?为什么需要 token 无感刷新?让我们想象一下有这么个场景:你登录一个系统成功后,玩了 10 分钟,发现登录失效了,又要你重新登录,然后又过 10 分钟,又失效了,又要重新登录,难不难受,那这是怎么造成的?是因为权限 token 有效时间很短造成的,不要问,为什么权限 token 过期时间这么短,因为需要实现单点登录。那什么是单点登录呢?请参考。在单点登录模式下,服务器在我们登录成功后发了两个 token 给我们,一个有效时间短的(有效时间 10 分钟),一个有效时间长的。

weixin_64684095的博客 917

Pinocchio 快速详细入门教程 —— 开源机器人运动学动力学库

本文介绍了机器人学中的数字机器人学、正逆运动学、动力学仿真与控制、最优控制等核心主题,以及Pinocchio库的应用。内容包括: 数字机器人学:通过UR5机器人模型演示了构型空间采样、碰撞检测、路径规划等基础操作,使用优化方法在约束条件下寻找有效构型。 运动学:详细讲解了二维和三维机器人的正运动学(构型到末端位置)和逆运动学(目标位置到构型),包括串联机械臂和并联机器人的处理。 动力学与控制:介绍了动力学仿真(如自由落体、摩擦效应)、PD控制、计算扭矩控制,以及接触仿真(碰撞检测与处理)。 最优控制:以独轮

机器人控制与仿真应用 2883

用 Axios 封装一个双 token 无感刷新

为了保证安全性,后端设置的Token不可能长期有效,过了一段时间Token就会失效。而发送网络请求的过程又是需要携带Token的,一旦Token失效,用户就要重新登陆,这样用户可能需要频繁登录,体验不好。为了解决这个问题,采取双Token(Access_Token,Refresh_Token)无感刷新,用户完全体会不到Token的变化,但实际上,Token已经刷新了。

猿特佳 2320

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VUE前端实现token的无感刷新

说实话,这个其实没啥好讲的,要说有复杂度的话,也主要是在后端。实现token无感刷新对于前端来说是一项十分常用的技术,其本质都是为了优化用户体验,当token过期时不需要用户调回登录页重新登录,而是当token失效时,进行拦截,发送刷新token的请求,获取最新的token进行覆盖,让用户感受不到token已过期。

老电影故事的博客 1万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

前端双token无感刷新详解

在介绍双token无感刷新之前,我们先简单介绍一下什么是token吧!token是一种用户标识,表示用户身份,类似于我们的身份证件。Token是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回Token给前端。前端可以在每次请求的时候带上Token证明自己的合法地位。如果这个Token在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。

小庄zzz的博客 2481

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

如何做到无感刷新token?

如何做到无感刷新token?

abcafdsgr123456789的博客 1282

如何实现无感刷新Token

5、后端接收到刷新Token请求后,首先验证Refresh Token的有效性、如果Refresh Token有效,则生成新的Access Token,并返回给前端。,如果Token未过期且有效,则处理请求并返回对应的结果,如果Token已过期或无效,则后端返回401未授权错误码给前端。6、前端收到新的Access Token后,更新本地存储中的Access Token,并重新发送之前被拦截的请求。6、前端收到新的Token后,更新本地存储中的Token,并重新发送之前被拦截的请求。

m0_65419210的博客 1233

vue2实现无感刷新token

在 Web 应用中,用户需要通过认证和授权才能访问受保护的资源。为了实现认证和授权功能,通常需要使用 Token 来标识用户身份并验证其权限。但是,Token 有时限制其有效期,以确保安全性。

欢迎来到我的前端博客!这里汇集了关于前端开发的最新技术、实用工具和经验分享。我将为你提供详细的教程、代码示例和实战案例,帮助你掌握Web开发的核心概念和技能。不论你是初学者还是有经验的开发者,这个博客都适合你。 2406

如何实现双Token无感刷新

为了解决这个问题,采取双Token(Access_Token,Refresh_Token)无感刷新,用户完全体会不到Token的变化,但实际上,Token已经刷新了。3.Access_Token过期后,前端携带Refresh_Token调用A接口得到新的Access_Token,把新的Access_Token替换旧的Access_Token存储起来。Refresh_Token:用于刷新Access_Token,即调用A接口需要携带Refresh_Token, 用它换得最新的Access_Token。

weixin_55862073的博客 1690
上一篇: 一个适合初级程序员学习的微商城项目,感觉收藏起来!!
下一篇: 字节一面:post 为什么会发送两次请求?被问懵了…
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值