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

如何通过 JWT 来解决登录认证问题

1. 问题引入

在登录功能的实现中

传统思路:

  1. 登录页面时把用户名和密码提交给服务器
  2. 服务器验证用户名和密码,并把检验结果返回给后端
  3. 如果密码正确,则在服务器端创建 session,通过 cookie 把 session id 返回给浏览器

但是正常情况下一个 web 应用是部署到多个服务器上的,通过 Nginx 等进行负载均衡,此时就可能出现这样的情况:用户登录请求之后把 session 存储在了第一台服务器上,但是后续的请求操作,例如查询等,就可能会转发到第二台服务器上,但是第二台服务器没有存储该用户的 session,就会让用户重新登录,这肯定是不合理的

解决方案:

  1. 对于服务端来说,上述出现的问题是由于 session 是默认存储在内存中的,服务器重启之后,session 就丢失了,如果把 session 存储在 Redis 中,那么就能共同访问,并且不丢失数据。
  2. 第二种方案就是引入 token,也就是令牌,用户登录之后,服务器对账号和密码进行验证,验证通过就生成一个令牌,并返回给客户端,客户端收到令牌之后,把令牌存储起来,之后再发起其他请求就带着令牌,处理请求的服务器校验令牌是否有效即可

引入令牌之后就解决了集群环境下的认证问题,并且减轻了服务器的存储压力,令牌由客户端存储,服务器只负责生成和校验

2. JWT 的介绍

官网:JSON Web Tokens - jwt.io

JWT 令牌本身是一个字符串,包括头部,载荷,签名三部分,将信息作为 JSON 对象进行传输

头部:包括令牌的类型和使用的哈希算法

载荷:存储的有效信息,为自定义内容

签名:用于防止 JWT 内容被篡改(并不是防止被解析),只要被篡改,令牌就会失效

3. JWT 的使用

首先需要导入对应的依赖:

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred --><version>0.11.5</version><scope>runtime</scope>
</dependency>

接下来就可以测试生成 token 了

//生成token
@Test
public void getToken() {String secret = "abcdefghijklmnopqrstuvwxyz";//设置key,用于签名Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));//载荷Map<String, Object> map = new HashMap<>();map.put("name", "zhangsan");map.put("id", 1);//生成tokenString compact = Jwts.builder().setClaims(map).signWith(key).compact();System.out.println(compact);
}

此时报出了一个错误,要求使用提供的方法来生成 key

接下来看怎么生成 key

@Test
public void genKey(){//生成keySecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);//转化为String类型String enconde = Encoders.BASE64.encode(secretKey.getEncoded());System.out.println(enconde);
}

生成之后就可以替换掉原来自定义的字符串了,再去生成 token

在官网中也是可以校验成功的

接下来看怎么通过方法来进行 token 的校验:

//校验token
@Test
public void parseToken(){String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiemhhbmdzYW4iLCJpZCI6MX0.xllreml0yt9aQDXSQe0ngQb45VpV5843rOEKdDQ4QCk";//JWT解析器JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();//对创建好的token进行解析Object body = build.parse(token).getBody();System.out.println(body);
}

如果说签名错了就无法正确解析了:

这就可以通过 try- catch 进行逻辑处理了:

根据这些就可以写一个工具类,服务端就可以直接调用了

@Slf4j
public class JwtUtil {//设置key,用于签名private final static String secret = "WHMgtn1tTrIxc00ys17ukp65bf2KZ0wrihyqynY18F8=sssss";private final static Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));private final static long expiration = 24 * 60 * 60 * 1000;//生成tokenpublic static String getToken(Map<String, Object> map) {return Jwts.builder().setClaims(map).setExpiration(new Date(System.currentTimeMillis() + expiration))//设置过期时间.setIssuedAt(new Date())  //设置签发日期.signWith(key).compact();}//校验tokenpublic static Claims parseToken(String token) {if (!StringUtils.hasLength(token)) {return null;}//JWT解析器JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();//对创建好的token进行解析Claims body = null;try {body = build.parseClaimsJws(token).getBody();return body;} catch (SignatureException e) {log.error("token非法...e{}", e.getMessage());} catch (ExpiredJwtException e) {log.error("token过期... e{}", e.getMessage());} catch (Exception e) {log.error("token解析失败,e{}", e.getMessage());}return body;}
}

相关文章:

如何通过 JWT 来解决登录认证问题

1. 问题引入 在登录功能的实现中 传统思路&#xff1a; 登录页面时把用户名和密码提交给服务器服务器验证用户名和密码&#xff0c;并把检验结果返回给后端如果密码正确&#xff0c;则在服务器端创建 session&#xff0c;通过 cookie 把 session id 返回给浏览器 但是正常情…...

高效集成:将聚水潭数据导入MySQL的实战案例

聚水潭数据集成到MySQL&#xff1a;店铺信息查询案例分享 在数据驱动的业务环境中&#xff0c;如何高效、准确地实现跨平台的数据集成是每个企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例——将聚水潭的店铺信息查询结果集成到MySQL数据库中&#xff0c;以供BI…...

Jenkins-基于 JNLP协议的 Java Web 启动代理

在上一篇的基础配置上进行以下步骤 工作流程&#xff1a; 通过 JNLP 启动代理&#xff0c;客户端从 Jenkins 服务器上下载一个 agent.jar 文件。该文件启动时&#xff0c;代理程序通过 JNLP 协议连接到 Jenkins 主节点。一旦连接成功&#xff0c;代理节点就可以执行从主节点分…...

Qt数据库操作-QSqlQueryModel 的使用

QSqlQueryModel 功能概述 QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能&#xff0c;但是 QSqlQueryModel 只能作为只读数据源使用&#xff0c;不可以编辑数据。QSqlQueryModel 类的主要函数如下&#xff1a; 接口…...

C语言编程1.21波兰国旗问题

题目描述 桌上有 n ( 1 < n < 10000 ) 面小旗&#xff0c;一部分是白旗&#xff0c;一部分是红旗(波兰国旗由白色和红色组成)。唯一允许的操作是交换两面小旗位置。请你设计一个算法&#xff0c;用最少的交换操作将所有的白旗都置于红旗的之前。 输入格式 第一行为一个…...

如何利用微型5G网关为智慧无人矿车提供精确定位

随着5G、AI、物联网技术的发展和普及&#xff0c;越来越多行业正在加快生产、运营、管理的无人化、数字化与智能化&#xff0c;以适应当前我国“智慧、绿色、低碳”的新型发展模式需要。其中矿产业就是典型场景之一。针对矿山场景的智慧化、无人化转型&#xff0c;佰马提供基于…...

使用docker-compese部署SFTPGo详解

官网&#xff1a;SFTP & FTP as a Managed Service (SaaS) and On-premise 一、SFTPGo简介 SFTPGo 是一款功能强大的文件传输服务器软件。它支持多种协议&#xff08;SFTP、SCP、FTP/S、WebDAV、HTTP/S&#xff09;和多个存储后端。 借助 SFTPGo&#xff0c;您可以利用本地…...

Ajax基础总结(思维导图+二维表)

一些话 刚开始学习Ajax的时候&#xff0c;感觉很模糊&#xff0c;但是好像学什么都是这样的&#xff0c;很正常&#xff0c;但是当你学习的时候要持续性敲代码&#xff0c;边敲代码其实就可以理解很多了。然后在最后的总结&#xff0c;其实做二维表之后&#xff0c;就可以区分…...

Spring Task和WebSocket使用

在现代 Web 应用中&#xff0c;WebSocket 作为一种全双工通信协议&#xff0c;为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能&#xff0c;使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 WebSocket…...

微信小程序 本地调试和vconsole可以 但在体验上页面不请求数据

微信小程序页面不请求数据 本地调试和vconsole可以 但在体验版页面不请求数据&#xff0c;如遇到这类问题基本都是一样的解决办法 1、如何调试找到问题 首先要把小程序本地设置的不校验合法域名关掉&#xff0c;不然本地一直都是好的 然后通过本地真机调试打断点找到问题位…...

QT:将QTableWidget内容写入txt文件中

文章详请&#xff1a;最近在做手在眼上的标定&#xff0c;首先要采集机械臂数据和图像数据&#xff0c;我使用tablewidget进行机械臂数据的显示&#xff0c;最后的计算需要将机械臂位姿数据存储在txt文件中。 引用&#xff1a;Qt如何保存tableWidget数据&#xff1f;_qt table…...

前端面试题(六)

1.let,var,const区别 1.作用域&#xff1a;  var&#xff1a;var声明的变量存在函数作用域或全局作用域&#xff0c;这意味着它们在声明它们的函数内部可见&#xff0c;而不在块级作用域内可见。 let和const&#xff1a;let和const声明的变量存在块级作用域&#xff0c;这…...

「Mac畅玩鸿蒙与硬件35」UI互动应用篇12 - 简易日历

本篇将带你实现一个简易日历应用&#xff0c;显示当前月份的日期&#xff0c;并支持选择特定日期的功能。用户可以通过点击日期高亮选中&#xff0c;还可以切换上下月份&#xff0c;体验动态界面的交互效果。 关键词 UI互动应用简易日历动态界面状态管理用户交互 一、功能说明…...

Leetcode581. 最短无序连续子数组(HOT100)

链接 我的代码&#xff1a; class Solution { public:int findUnsortedSubarray(vector<int>& nums) {vector<int> res nums;sort(res.begin(),res.end());int l 0,r nums.size()-1;while(nums[l]res[l]){l;if(lnums.size()){return 0;}}while(nums[r]res…...

HTML前端开发-- Flex布局详解及实战

引言 Flex布局&#xff0c;全称为Flexible Box Layout&#xff0c;是一种现代CSS布局技术&#xff0c;它提供了一种更有效的方式来设计响应式布局和复杂页面布局。本文将详细介绍Flex布局的基本概念、属性以及实战应用。 一、基本概念 Flex布局的核心是Flex容器&#xff08;…...

基于JWT跨语言开发分布式业务系统的挑战与实践:多语言协作的最佳方案

在现代分布式架构下&#xff0c;开发团队往往由来自不同技术栈和开发语言的工程师组成。如何有效地管理这些开发人员的协作&#xff0c;尤其是在实现跨语言的认证与授权机制时&#xff0c;成为了开发者面临的一个重大挑战。JSON Web Token&#xff08;JWT&#xff09;作为一种轻…...

二分法篇——于上下边界的扭转压缩间,窥见正解辉映之光(2)

前言 上篇介绍了二分法的相关原理并结合具体题目进行讲解运用&#xff0c;本篇将加大难度&#xff0c;进一步强化对二分法的掌握。 一. 寻找峰值 1.1 题目链接&#xff1a;https://leetcode.cn/problems/find-peak-element/description/ 1.2 题目分析: 题目要求返回数组内…...

什么是 Kata Containers?

什么是 Kata Containers&#xff1f; Kata Containers 是一种结合了容器技术和虚拟机技术的轻量级运行时&#xff0c;旨在提供容器的速度和虚拟机的安全性。它将容器运行在一个隔离的虚拟机中&#xff0c;从而大幅提升安全性&#xff0c;同时保持容器的高效性。 Kata Contain…...

SpringMvc项目配置RabbitMq

前言&#xff1a;只有消费者部分&#xff0c;没有记录生产者部分 结构图 配置类 可以xml配置&#xff0c;也可以配置类&#xff0c;二者可以相互转化。两种bean注入的方式。 import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.spring…...

shell编程(4)脚本与用户交互以及if条件判断

shell编程&#xff08;4&#xff09;脚本与用户交互以及if条件判断 声明&#xff01; 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;…...

Taotoken的计费透明与账单追溯功能让我的每一分钱都花得明白

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken的计费透明与账单追溯功能让我的每一分钱都花得明白 作为独立开发者或小型技术团队的负责人&#xff0c;管理项目成本是日…...

GEO工具红黑榜:有的在“监测“,有的在“收智商税“

2026年&#xff0c;AI搜索已承接超过40%的传统搜索查询量&#xff0c;品牌面临的不再是"百度一下"的竞价排名&#xff0c;而是AI助手直接给出的"默认答案"。当用户问ChatGPT"推荐一款面霜"或向豆包询问"哪个在线教育平台更好"时&#…...

【流体】基于matlab二维稳态不可压缩层流通道流利用FVM和SIMPLE 解平行板间层流的速度、压力和温度【含Matlab源码 15558期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到海神之光博客之家&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49…...

前端实战:CSS 实现经典对联式悬浮广告

一、效果介绍对联广告是网页中非常经典的广告布局&#xff0c;特点&#xff1a;左右两侧各一个广告栏&#xff0c;像对联一样悬挂页面上下滚动&#xff0c;广告固定不动、悬浮跟随屏幕中间是网站主体内容&#xff0c;互不遮挡、互不影响核心技术&#xff1a;CSS fixed 固定定位…...

简单说明--程序系统如何对用户身份证实名认证接口api

程序系统对注册用户身份认证&#xff0c;接口将【身份证号码、姓名】上传至接口API判断是否匹配 请求数据&#xff1a; bodys.put("idNo", "330421190210182345"); bodys.put("name", "张某某");响应数据&#xff1a; {"name&quo…...

黑苹果配置终极简化:OpCore Simplify三步搞定OpenCore EFI

黑苹果配置终极简化&#xff1a;OpCore Simplify三步搞定OpenCore EFI 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的黑苹果配置而烦恼吗…...

第P5周:Pytorch实现运动鞋识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 个人体悟&#xff1a;今天学习了动态学习率有种豁然开朗的感觉&#xff0c;在引入该部分之后模型的学习速度和学习质量都得到了较大提升&#xff01;...

Runtime不是跑kernel的——它是昇腾CANN里的执行层

前言 昇腾NPU上的算子是怎么跑起来的&#xff1f;有人说"runtime就是负责跑kernel的"&#xff0c;有人说"runtime管内存分配"&#xff0c;还有人说"runtime就是CUDA runtime的对应物"。这些答案都有对的地方&#xff0c;但都没说到根子上。 Ru…...

3个关键技巧:用ProperTree告别Plist编辑的繁琐与混乱

3个关键技巧&#xff1a;用ProperTree告别Plist编辑的繁琐与混乱 【免费下载链接】ProperTree Cross platform GUI plist editor written in python. 项目地址: https://gitcode.com/gh_mirrors/pr/ProperTree 你是否曾经面对macOS配置文件时感到手足无措&#xff1f;那…...

从手机拍照到视频播放:一文看懂YUV(NV12/YUV444)格式为什么无处不在

从手机拍照到视频播放&#xff1a;YUV格式的技术演进与行业实践 当你用手机拍摄一张照片或录制一段视频时&#xff0c;图像数据在传感器采集后经历了一系列复杂的格式转换过程。这些转换不仅关乎图像质量&#xff0c;更直接影响着存储空间、处理速度和传输效率。在众多色彩编码…...