Java如何做到无感知刷新token含示例代码(值得珍藏)

1. 前言

在系统页面进行业务操作时,有时会突然遇到应用闪退,并被重定向至登录页面,要求重新登录。此问题的出现,通常与系统中用于存储用户ID和token信息的Redis缓存有关。具体来说,这可能是由于token过期所导致的身份验证失效。

要解决这个问题,可以采用两种策略:一是自动刷新token,二是token续约。通过在验证用户权限的同时为用户生成新的token并返回给客户端,可以确保客户端及时更新本地存储的token。此外,设置定时任务来刷新token也是一个有效的方法。这样,即使在token即将过期的情况下,也可以通过增加其有效时间来避免应用闪退的问题。

在这里插入图片描述

2. 自动刷新token

自动刷新token是一种后端解决方案,旨在解决token过期问题。后端会检查每个token的过期时间,一旦发现某个token即将过期,就会在请求头中添加一个新的token。前端在接收到请求时,会拦截该请求并从请求头中获取新的token。如果新旧token不一致,前端会直接更新本地的token,从而确保后续请求能够正常进行。这种方法可以有效避免因token过期而导致的系统闪退问题,提高了系统的稳定性和安全性。

2.1 后端实现方案

2.1.1 先引入依赖

<dependencies>  
    <!-- Java JWT -->  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-api</artifactId>  
        <version>0.11.2</version> <!-- 使用最新版本 -->  
    </dependency>  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-impl</artifactId>  
        <version>0.11.2</version> <!-- 使用最新版本 -->  
        <scope>runtime</scope>  
    </dependency>  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-jackson</artifactId>  
        <version>0.11.2</version> <!-- 使用最新版本 -->  
        <optional>true</optional>  
    </dependency>  
    <!-- 其他必要的依赖项 -->  
</dependencies>

2.1.2 生成token的代码

import java.nio.charset.StandardCharsets;  
import java.util.Base64;  
import java.util.Date;  
  
import io.jsonwebtoken.Claims;  
import io.jsonwebtoken.Jwts;  
import io.jsonwebtoken.SignatureAlgorithm;  
import io.jsonwebtoken.security.Keys;  
  
public class TokenGenerator {  
      
    // 用于生成Token的密钥  
    private static final String SECRET = "your_secret_key"; // 请使用一个安全的密钥  
      
    /**  
     * 生成一个新的Token。  
     *   
     * @param userId 用户ID  
     * @return 生成的Token字符串  
     */  
    public static String generateToken(String userId) {  
        // 设置Token的有效期为1小时(3600秒)  
        long expirationTime = 3600L;  
          
        // 创建Token的主体部分,包括用户ID和过期时间戳  
        String tokenBody = userId + "|" + System.currentTimeMillis() + "|" + expirationTime;  
          
        // 使用Base64对Token的主体部分进行编码,以便在Token中传输  
        String encodedBody = Base64.getEncoder().encodeToString(tokenBody.getBytes(StandardCharsets.UTF_8));  
          
        // 创建Token的头部部分,包括签名算法和密钥标识符(通常为密钥的SHA-256摘要)  
        String header = "{\"alg\":\"" + SignatureAlgorithm.HS256 + "\",\"typ\":\"JWT\"}";  
        String encodedHeader = Base64.getEncoder().encodeToString(header.getBytes(StandardCharsets.UTF_8));  
          
        // 使用密钥对Token的头部和主体部分进行签名,生成最终的Token  
        String token = Jwts.builder()  
                           .setHeader(encodedHeader) // 设置头部信息  
                           .setClaims(Claims.builder().subject(encodedBody).expiration(new Date(System.currentTimeMillis() + expirationTime * 1000)).build()) // 设置主体信息和过期时间戳  
                           .signWith(Keys.hmacShaKeyFor(SECRET)) // 使用HMAC SHA-256算法和密钥进行签名  
                           .compact(); // 生成最终的Token字符串  
          
        return token; // 返回生成的Token字符串  
    }  
}

2.1.3 测试生成token

import java.util.Base64;  
  
public class TokenGeneratorExample {  
    public static void main(String[] args) {  
        String userId = "12345"; // 替换为实际的用户ID  
        String token = TokenGenerator.generateToken(userId);  
        System.out.println("Generated Token: " + token);  
    }  
}

2.2 前端续约token

token续约更倾向于采用前端解决方案,即由前端来处理token的过期时间。首先,前端和后端需要协商并确定一个用于token续约的接口。当前端检测到某个token即将过期时,它会向后端发送该token,然后由后端来延长该token的过期时间。

在前端实现方案中,使用的是双Token方式,即access-token(AT)和refresh-token(RT)。而对于纯后端方式,则只使用access-token。

那么,AT和RT之间有什么区别?为什么需要RT?实际上,AT的暴露机会更多,因为每个请求都需要携带它。为了降低被劫持的风险,AT的过期时间通常设置得较短。而RT仅在auth服务中用于刷新AT,因此它的过期时间通常设置得较长,以增加便利性。

AT和RT的设计是为了提高网络传输的安全性。在网络传输过程中,AT容易暴露,因为它的过期时间较短。通过使用AT和RT,可以降低这种风险。这种设计已经成为了一种标准的安全处理方式,就像https之于http一样,无需再探讨其合理性。

2.3 疑问及思考

当用户在前端表单页面填写内容时,如果长时间没有进行请求发送,导致Token过期,后端返回401错误,这是一个常见的问题。下面是对这个问题的重写:

如果前端有一个表单页面,用户在长时间没有发送请求的情况下填写了表单,然后尝试提交,但后端返回了401错误(表示未授权或Token已过期),该如何解决?

对于这种情况,解决方案可以考虑以下几点:

  • 对于纯后端解决方案,一种可能的做法是让前端在表单填写过程中进行特殊处理。如果提交表单后返回401错误,前端可以将表单数据存储在本地存储中,然后跳转到登录页面。用户登录成功后,页面将返回表单页面,并从本地存储中取出之前保存的数据,重新填充到表单中。

  • 对于前端解决方案,当Token过期时(无论是access-token还是refresh-token),可以采取以下措施:

    • 监听refresh-token的过期时间,当它接近过期时,向后端发起请求来刷新refresh-token。这样可以确保在Token过期之前进行刷新,避免提交表单时出现401错误。

    • 实现类似草稿箱的功能,将表单数据保存在前端本地存储中。当检测到Token过期时,可以提示用户重新登录,并在登录成功后恢复之前保存的数据。这样即使Token过期,用户也可以重新登录并继续之前未完成的操作。

    • 以上解决方案可以帮助解决Token过期导致的问题,提高用户的体验和系统的安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/332125.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

shell编程-3

文章目录 shell学习第三天while 循环第一天的小游戏练习: 编写抽同学回答问题的脚本要想让这个脚本永久有效如何知道两个文件里的内存一样&#xff1f;如何判断某个人已经抽过了 文本处理相关命令seqxargsuniqsorttrcutawkpastesplitcoljoin小结一下作业 小知识点写脚本的流程怎…

【蓝桥杯EDA设计与开发】资料汇总以及立创EDA及PCB相关技术资料汇总(持续更新)

[18/01/2024]&#xff1a;目前为了准备蓝桥杯做一些资料贴&#xff0c;于是写下这一篇博客。 各种资料均来源于网络以及部分书籍、手册等文档&#xff0c;参考不保证其准确性。 如果在准备蓝桥杯&#xff0c;可与我私信共同学习&#xff01;&#xff01;&#xff01;&#xf…

【人工智能课程】计算机科学博士作业一

【人工智能课程】计算机科学博士作业一 1 任务要求 模型拟合&#xff1a;用深度神经网络拟合一个回归模型。从各种角度对其改进&#xff0c;评价指标为MSE。掌握技巧&#xff1a; 熟悉并掌握深度学习模型训练的基本技巧。提高PyTorch的使用熟练度。掌握改进深度学习的方法。 …

sc.pl.umap 画feature plot

今天有时间尝试测试了这个scanpy的feature plot,其实很简单&#xff0c;就是使用 sc.pl.umap(adata,color"gene name"), 但是这个地方就有一个问题&#xff0c;这个画出来的值是原始的基因值还是scale之后的&#xff0c;这个我得搞清楚 首先看使用例子&#xff0c;参…

Linux shell编程学习笔记40:stat命令

程序员必备的面试技巧 “程序员必备的面试技巧&#xff0c;就像是编写一段完美的代码一样重要。在面试战场上&#xff0c;我们需要像忍者一样灵活&#xff0c;像侦探一样聪明&#xff0c;还要像无敌铁金刚一样坚定。只有掌握了这些技巧&#xff0c;我们才能在面试的舞台上闪耀…

QT-贪吃小游戏

QT-贪吃小游戏 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include "Snake.h" #include "Food.h" #include "Stone.h" #include "Mushroom.h" #include "Ai.h" #include "Game.h" #inclu…

[Linux 进程(五)] 程序地址空间深度剖析

文章目录 1、前言2、什么是进程地址空间&#xff1f;3、进程地址空间的划分4、虚拟地址与物理地址的关系5、页表的作用扩展 6、为什么要有地址空间&#xff1f; 1、前言 Linux学习路线比较线性&#xff0c;也比较长&#xff0c;因此一个完整的知识点学习就会分布在两篇文章中&…

zabbix客户端配置及自定义监控

部署zabbix客户机 1.服务端和客户端都配置时间同步 yum install -y ntpdate ntpdate -u ntp.aliyun.com 2.服务端和客户端都设置 hosts 解析 cat > /etc/hosts << EOF 172.16.23.16 localhost 172.16.23.17 zbx-server EOF 3.被监控端 //设置 zabbix 的下载源&…

年龄性别预测1:年龄性别数据集说明(含下载地址)

年龄性别预测1&#xff1a;年龄性别数据集说明(含下载地址) 目录 年龄性别预测1&#xff1a;年龄性别数据集说明(含下载地址) 1.前言 2.MegaAge_Asian 3.MORPH 4.IMDB-WIKI 5.数据集下载 6.年龄性别预测和识别(Python/C/Android) 1.前言 本项目将实现年龄性别预测和识…

『 C++ 』红黑树RBTree详解 ( 万字 )

文章目录 &#x1f996; 红黑树概念&#x1f996; 红黑树节点的定义&#x1f996; 红黑树的插入&#x1f996; 数据插入后的调整&#x1f995; 情况一:ucnle存在且为红&#x1f995; 情况二:uncle不存在或uncle存在且为黑&#x1f995; 插入函数代码段(参考)&#x1f995; 旋转…

【C++入门】C++ STL中string常用函数用法总结

目录 前言 1. string使用 2. string的常见构造 3. string类对象的访问及遍历 迭代器遍历&#xff1a; 访问&#xff1a; 4. string类对象的容量操作 4.1 size和length 4.2 clear、empty和capacity 4.3 reserve和resize reserve resize 5. string类对象的修改操作 push_back o…

version-polling一款用于实时检测 web 应用更新的 JavaScript 库

为了解决后端部署之后&#xff0c;如何通知用户系统有新版本&#xff0c;并引导用户刷新页面以加载最新资源的问题。 实现原理 1.使用 Web Worker API 在浏览器后台轮询请求页面&#xff0c;不会影响主线程运行。 2.命中协商缓存&#xff0c;对比本地和服务器请求响应头etag字…

施耐德PLCTM200CE 如何实现远程上传下载程序?

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台施耐德TM200CE PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff0…

Unity3D和three.js的比较

一、Unity3D和three.js简介 Unity3D是一款跨平台的游戏引擎,可以用于开发2D和3D游戏。它提供了一个可视化的开发环境,包含了强大的编辑器和工具,使开发者可以方便地创建游戏场景、添加物体、设置物理效果、编写脚本等。Unity3D支持多种平台,包括PC、移动设备、主机等,可以…

HBuilder 创建的 Uui-App项目 如何发布到微信小程序

需提前准备的工具&#xff1a;HBuilder X &#xff0c;微信开发者工具 目录 一、微信小程序账号申请 二、在微信开发者工具中打开服务端口 三、 在HBuilder创建Uni-App项目&#xff0c;并与微信小程序开发工具进行交互预览测试 四、 发布Uni-App项目 五、 微信线上发布运行 …

PXE和kickstart无人值守安装

PXE高效批量网络装机 引言 1.系统装机的引导方式 启动 操作 系统 1.硬盘 2.光驱&#xff08;u盘&#xff09; 3.网络启动 pxe 重装系统&#xff1f; 在已有操作系统 新到货了一台服务器&#xff0c; 装操作系统 系统镜像 u盘 光盘 pe&#xff1a; 小型的 操作系统 在操…

(一)SpringBoot3---尚硅谷总结

示例Demo&#xff1a; 1、我们先来创建一个空工程&#xff1a; 2、我们通过Maven来创建一个Module&#xff1a; JDK版本需要选择17以及以上&#xff0c;如果没有的话你就下载一个&#xff1a; 3、让此Maven项目继承父项目: 所有的Springboot项目都必须继承自spring-boot-start…

【PS】PS设计图欣赏、学习、借鉴

【PS】PS设计图欣赏、学习、借鉴 bilibili萌新PS学习计划&#xff1a;PS教程全套零基础教学视频&#xff08;全套81节全新版本&#xff09;

编译FFmpeg4.3.1 、x264并移植到Android

1、前言 FFmpeg 既是一款音视频编解码工具&#xff0c;同时也是一组音视频编解码开发套件。 2、准备工作 系统&#xff1a;LinuxNDK&#xff1a;android-ndk-r21b-linux-x86_64.zipFFmpeg&#xff1a;ffmpeg-snapshot.tar.bz2x264&#xff1a;x264 3、下载NDK 在linux环境中…

window11环境安装jdk17并配置环境变量

目录 一、下载地址二、安装步骤三、环境变量配置四、环境变量配置是否成功的测试 一、下载地址 https://www.oracle.com/java/technologies/downloads/#jdk17-windows 二、安装步骤 双击已下载的 jdk-17_windows-x64_bin.exe 安装包&#xff0c;点击【下一步】&#xff0c;…