springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)

接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上,基本完成用户模块的登录接口的主逻辑以及提到了问题:"用户未登录,需要通过登录,获取到令牌进行登录认证,才能使用其他功能的接口"。具体往回看了解的链接如下。springboot实战学习(6)(用户模块的登录认证)(初识令牌)(JWT)-CSDN博客文章浏览阅读2次。本篇博客是在处理用户模块中登录认证时遇到需要解决的问题。因为未登录时,需要做到无法访问和使用其他功能的接口。也就提到了令牌的作用以及满足令牌的规范"JWT"。具体的学习下篇博客进行学习...https://blog.csdn.net/m0_74363339/article/details/142365524?spm=1001.2014.3001.5502

接下来就去认真了解和学习Web登录认证中常用的令牌规范——>"JWT"。

目录

一、JWT(令牌规范)

(1)基本介绍

(2)基本组成

(I)解释上方图片(JWT令牌字符串)

(II)总结组成

二、程序中使用JWT令牌 

(1)回顾与思考

三、JWT令牌的生成

(1)JWT令牌示范

(1)如何生成

(2)如何使用生成"JWT令牌"工具

(I)第一步。导入工具的坐标(依赖)

(II)第二步。调用API,生成令牌。

(III)生成"JWT令牌"的代码不需要去记忆

(3)IDEA中写单元测试的方法测试生成JWT令牌

四、JWT令牌的验证

(1)DEA中写单元测试的方法测试"JWT令牌"的验证

(2)测试因篡改"JWT令牌"导致验证失败的几种情况

(I)篡改JWP令牌"头部部分"进行验证。

​编辑

(II)篡改JWP令牌中间"载荷部分"进行验证。

(III)篡改JWP令牌尾部"数字签名"(篡改密钥)进行验证。

(3)处理因篡改JWT令牌的数据导致的异常

(I)如果篡改了头部和载荷部分的数据,那么验证失败。

(II)如果篡改了密钥数据,那么验证失败。

(III)如果超过设定的Token令牌过期时间,那么验证失败。

(4)关于"JWT令牌"验证的注意事项

五、总结

(1)JWT令牌的组成

(2)JWT令牌的使用

(3)尾言


一、JWT(令牌规范)

(1)基本介绍
  • JWT的全称:JSON Web Token
JSON Web Tokens - jwt.ioJSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).icon-default.png?t=O83Ahttps://jwt.io/

也就是用于Web领域的基于JSON格式的令牌

  • 定义了一种简洁的、自包含的格式,用于通信双方以json数据格式安全的传输信息。

(JSON是一种文本数据格式,来源于JavaScript的对象语法。

(2)基本组成

(I)解释上方图片(JWT令牌字符串)
  • 上面展示的它是前后端交互时传输的字符串。而这个字符串是由JSON格式的字符串编码得来的字符串。可以看到上面字符串有两个小".",它就是把这整个字符串分为三个部分。而"分割"的每一个小串,对应着Token令牌的一部分。
  • 第一部分是头。它是由JSON字符串编码得来的。这个部分的字符串会记录两个信息。第一个是"alg"(它是加密算法,防篡改),而"type"(是JWT)。
  • 第二部分是"有效载荷"。它是也是一段字符串。而在这段字符串中,他会存放我们的业务数据。比如存放用户的id、用户的username等等。这段字符串编码后,也会得到上面Token令牌里面的这一段。 

  • 而对应的JSON格式的字符串,是如何转换为上面Token令牌中展示的这一段"特殊长的字符串"呢?在JWT中会借助于"base64"这种编码方式完成。而"base64"可以将任意数据转换成64个可打印字符('a'-'z'、'A'-'Z'、'0'-'9'等等)。这些64个可打印字符最重要的特点就是:"通用",在任意场景都可以被支持。
  • 将JSON格式的字符串转换为64个可打印的字符串,原因是为了提供Token令牌的实用性。记得"base64"仅仅是一种编码方式,而不是加密。因此记得在Token令牌的第二部分"有效载荷",一定注意不要放私密数据(比如用户密码等),不然不安全。


  • 最后一部分叫做"数字签名"。它是将第一部分以及第二部分,借助于密钥和加密算法,通过加密得来的。而这里的加密算法,是通过头部的"alg"来制定的。密钥可以在程序中单独配置。
  • 有了这个数字签名,就可以防篡改,确保Token是安全的。因为将来即使篡改了第一和第二部分,但第三部分是不能篡改的,因为是加密后的字符串。将来JWT再去解析Token令牌时,通过解密第三部分,得到"头部"与"载荷",再拿到解密的内容与用户传递的内容进行比对,如果不一样,就不让访问。
(II)总结组成

二、程序中使用JWT令牌 

(1)回顾与思考
  • 回到之前的所完成用户模块的注册接口与登录接口的主逻辑。

springboot实战学习笔记(5)(用户登录接口的主逻辑)-CSDN博客

  • 现在需要在用户登录之后生成一个"JWT令牌",生成了之后还需要把"JWT令牌"响应给浏览器。
  • 将来浏览器再去访问服务器上的其它资料时,会携带这个令牌访问。这时服务器就能够得到这个令牌,并且还需要去验证这个令牌的合法性。如果令牌合法、没有被篡改,就正常提供服务,反之。
  • 需要学习如何生成令牌?如何验证令牌?

三、JWT令牌的生成

(1)JWT令牌示范

(1)如何生成
  • 可以自己手写,毕竟JWT是一个令牌的规范写法。而是规范,大家都可以实现的。
  • 有人提供了生成"JWT令牌"的工具,所以可以直接使用这些工具即可。
(2)如何使用生成"JWT令牌"工具
(I)第一步。导入工具的坐标(依赖)
  • 引入的是java-jwt

  • 引入坐标时,报错,记得尝试刷新一个Maven

  • 因为我们当前写的"生成令牌"或者"验证令牌"代码,它仅仅是一个测试的代码。所以需要把它写到单元测试里面。所以还要引入单元测试的坐标

  • springboot为了更方便的测试spring程序,提供了springboot整合单元测试的一个起步依赖。

  • 添加完毕,一定记得刷新Maven。

(II)第二步。调用API,生成令牌。
(III)生成"JWT令牌"的代码不需要去记忆
  • 因为将来在公司中使用的时候,都是使用提供好的工具类,然后直接调用即可
(3)IDEA中写单元测试的方法测试生成JWT令牌
  • 在test目录的feisi目录下,新建一个类"JwtTest"。在这个类的内部去写单元测试的代码。

  • 新建一个方法testGen(),并且需要在方法上添加一个注解@Test

  • 如果要生成令牌,就要调用JWT的API。然后先调用其create()方法。
  • 然后利用链式编程的方式来调用方法。首先调用第一个方法"withClaim()",这个方法的作用是添加"载荷"(前面讲过)。

  • 这个添加载荷的方法就是:第一值传入键的名字(name)(如这里设置为"user",那么将来这个载荷就是承载着用户相关的信息),第二个参数值放一个map集合,比如user将来肯定有"id"、"username"等等。
JWT.create().withClaim("user",claims);
  • 所以接着就要创建一个Map类型的集合。指定其键是"String"类型,而值是"Object"类型的
Map<String, Object> claims = new HashMap<>();
  • 有了这个claims集合,就可以调用方法put()。如下添加。这样就提供添加"载荷"的方式,把当前用户信息添加进去了。
claims.put("id",1);claims.put("username","张三");
  • 接下来JWT.create().后面还可以添加几个方法。

  • .withExpiresAt()。这是添加过期时间。也就是登录时获得的令牌是有登录有效期的,时间过了,就需要重新登录。将来的Token令牌是有有效期的。
  • 里面是需要一个Data对象。直接new Data()。但是这个是当前的时间,所以还需要通过System提供的获取当前毫秒值的方法,再重新new一个Data对象。往后延迟指定一段时间。
  • 当前毫秒值+1000*60*60*12(也就是延后12个小时)
JWT.create().withClaim("user",claims).withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12));

  • sign()方法。"sign"是签名的意思。也就是如上面说的数字签名,加密用的。方法参数需要指定一个加密算法。这里选择HMAC256()这个算法。
  • 在指定算法的时候,需要指定一个密钥。这个是由自己定就行,就是一个字符串。但是它是加密的密钥,所以不要泄露,不然不能防篡改,保证安全。
.sign(Algorithm.HMAC256("feisi"));//指定算法,配置密钥

  • 这几个方法一旦调用,我们的Token令牌就能生成。所以就要去接收一下Token。
package com.feisi;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.junit.jupiter.api.Test;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JwtTest {//生成JWT令牌的方法@Testpublic void testGen(){Map<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("username","张三");//生成JWT代码String token = JWT.create().withClaim("user",claims) //添加载荷.withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12)) //添加过期时间.sign(Algorithm.HMAC256("feisi"));//指定算法,配置密钥//打印输出到控制台,查看生成的token令牌System.out.println(token);}
}

  • 最后运行一下这个测试类的方法。这样"JWT令牌"的生成就完成了。

四、JWT令牌的验证

(1)DEA中写单元测试的方法测试"JWT令牌"的验证
  • 首先这一部分的代码也不需要去背或者记忆。
  • 接着上面,在"testGen()"方法下添加一个方法"testParse()"。
  • 也是一样记得添加单元测试的注解@Test


  • 接着定义一个字符串"token",模拟存储用户传递给浏览器的token令牌。
  • 而这个token的值就用上面控制台打印的token令牌字符串就行。
//验证JWT令牌的方法@Testpublic void testParse(){//定义字符串,模拟用户传递给浏览器的token令牌//这个token就用上面生成的token令牌字符串就行String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"+".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3MjcwMzg2MDl9"+".LgfVNY-OAkjAps8yQXDkKyCIRbWw5jNQiNZwwbMf2F4";}

  • 接着开始提供验证了。去提供调用JWT这个类里面的一个静态方法"require()"。这是申请一个JWT的验证器。
  • 而这个方法里面的参数需要传递一个算法。之前加密用的算法,解密也要同样用一样的算法。直接复制过来。
  • 然后再调用一个".build()"方法去生成验证器。再用一个变量"jwtVerifier"给他存起来。
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("feisi")).build();

  • 有了这个变量之后,就可以调用验证器的方法,去验证这个token令牌字符串。
  • 调用方法".verify()",把之前控制台的token传递给它。


  • 它可以去解析这个token令牌。然后生成一个解析后的JWT对象。
DecodedJWT decodedJWT = jwtVerifier.verify(token); //验证token,生成一个解析后的JWT对象
  • 如果能正常的解析成功之后。那么就意味着可以从变量"decodedJWT"里面获取到当前的"头部"或者"载荷"以及"数字签名"等等。
  • 则调用它的一个方法:"GetClaims()",而它会得到所有的"载荷"。用Map对象的变量去接收一下它。
Map<String, Claim> claims = decodedJWT.getClaims();
  • 然后我们指定获取键名(name)为"user"的载荷。并且把得到的结果输出到控制台里面。
package com.feisi;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JwtTest {//生成JWT令牌的方法@Testpublic void testGen(){Map<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("username","张三");//生成JWT代码String token = JWT.create().withClaim("user",claims) //添加载荷.withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12)) //添加过期时间.sign(Algorithm.HMAC256("feisi"));//指定算法,配置密钥//打印输出到控制台,查看生成的token令牌System.out.println(token);}//验证JWT令牌的方法@Testpublic void testParse(){//定义字符串,模拟用户传递给浏览器的token令牌//这个token就用上面生成的token令牌字符串就行String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"+".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3MjcwMzg2MDl9"+".LgfVNY-OAkjAps8yQXDkKyCIRbWw5jNQiNZwwbMf2F4";JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("feisi")).build();DecodedJWT decodedJWT = jwtVerifier.verify(token); //验证token,生成一个解析后的JWT对象Map<String, Claim> claims = decodedJWT.getClaims();System.out.println(claims.get("user"));}
}

  • 得到控制台的正常输出,如:"id,1"、"username,"张三""等等就解析成功了!
  • 正常的解析成功如下。


(2)测试因篡改"JWT令牌"导致验证失败的几种情况
(I)篡改JWP令牌"头部部分"进行验证。

(II)篡改JWP令牌中间"载荷部分"进行验证。

  • 所以我们的JWT令牌是具体放篡改的功能的。

(III)篡改JWP令牌尾部"数字签名"(篡改密钥)进行验证。
  • 篡改了原来设定的密钥"feisi"改成"fesi"。


(3)处理因篡改JWT令牌的数据导致的异常
(I)如果篡改了头部和载荷部分的数据,那么验证失败。
(II)如果篡改了密钥数据,那么验证失败。
(III)如果超过设定的Token令牌过期时间,那么验证失败。

Token过期

  • 例如如下情况:报错提示"这个Token令牌"已经过期。

(4)关于"JWT令牌"验证的注意事项

五、总结

(1)JWT令牌的组成

  • "载荷"这一块要注意。不要存放一些私密信息,因为"base64"算法不是一个加密算法,它是公开的,每个人都能使用
  • 通过密钥与加密算法去验证Token令牌的合法性
(2)JWT令牌的使用

(借助工具:"JAVA-JWT")

(3)尾言

下篇博客就要开始继续完成用户登录认证的接口开发了!也就是把令牌的生成与验证加入到登录功能中

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DRF实操学习——收货地址的设计

DRF实操学习——收货地址的设计 1.行政区划表的设计2. 行政区划表接口演示1.返回所有的省份2. 查询指定上级行政区划的所有子区划&#xff0c;以及展示自身区划 3.行政区划表接口重写补充&#xff1a;前端请求逻辑4. 优化5.收货地址的设计6. 收货地址表接口重写7.优化1. 优化返…

示例说明:elasticsearch实战应用

Elasticsearch 是一个基于 Lucene 的分布式搜索和分析引擎&#xff0c;广泛应用于日志分析、全文搜索、数据可视化等领域。以下是 Elasticsearch 实战应用的一些关键点和步骤&#xff1a; 1. 环境搭建 首先&#xff0c;你需要在你的环境中安装和配置 Elasticsearch。 安装 E…

一个 Java 语言简化处理 PDF 的框架,提供了一套简单易用的 API 接口,满足多样化需求又能简化开发流程的处理方案(附教程)

前言 当前市面上处理 PDF 文件的工具众多&#xff0c;但它们往往存在一定的局限性&#xff0c;比如复杂交互、功能单一等问题。尤其对于那些需要频繁生成或编辑 PDF 文档的应用场景来说&#xff0c;找到一个既能满足多样化需求又能简化开发流程的处理方案显得尤为重要。那么&a…

中国的互联网电商,终于还是“连上了”

什么才是更好的互联网&#xff1f; 答案很简单&#xff1a;真正的互联。 9月26日&#xff0c;据市场消息&#xff0c;京东物流和菜鸟速递将分别接入淘天、京东平台。同时&#xff0c;京东也将在“双11”前开通支付宝支付&#xff0c;时隔13年再度携手阿里支付体系。 消息一出…

【x**3专享#2】编译 uboot 和 kernel 的文件结构

虚拟机交叉编译环境配置及内核编译步骤说明书 请先查看前篇文章内容 1. 获取虚拟机 IP 地址 打开虚拟机终端&#xff0c;执行以下命令查看虚拟机 IP 地址&#xff1a;ifconfig或者ip addr记录 eth0 或 ens33 等网络接口的 inet 后面的 IP 地址 2. 使用 Xftp 连接虚拟机 打开…

Springboot中yml文件不生效原因分析及解决

在Spring Boot项目中&#xff0c;YML文件是常用的配置文件格式。然而&#xff0c;有时你可能会遇到YML文件中的配置不生效的问题。本文将分析可能的原因并提供解决方案。 1. 格式错误 YML文件非常敏感&#xff0c;任何缩进或语法错误都可能导致配置不被解析。确保使用两个空格…

基于YOLOv5s的无人机航拍输电线瓷瓶检测(附数据集与操作步骤)

本文主要内容:详细介绍了无人机航拍输电线瓷瓶检测的整个过程&#xff0c;从创建数据集到训练模型再到预测结果全部可视化操作与分析。 文末有数据集获取方式&#xff0c;请先看检测效果 现状 输电线路绝缘瓷瓶的检测主要依赖人工巡检。巡检人员需携带专业设备&#xff0c;攀…

Python:百度贴吧实现自动化签到

早知道&#xff0c;还是python。 Github项目仓库在这。 相关API 签到贴吧列表 签到分为两个接口&#xff0c;PC端签到一次经验2&#xff0c;而移动端签到则是一次经验6。该用哪个接口已经很明显了。不过这里还是列出PC端的签到API。 # PC端签到接口 # sign_url "https:…

ROS理论与实践学习笔记——2 ROS通信机制之通信机制实践

5.1 话题发布 需求描述&#xff1a;编码实现乌龟运动控制&#xff0c;让小乌龟做圆周运动。 实现分析&#xff1a; ①乌龟运动控制实现&#xff0c;关键节点有两个&#xff0c;一个是乌龟运动显示节点 turtlesim_node&#xff0c;另一个是控制节点&#xff0c;二者是订阅发布模…

用Swift实现验证回文字符串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回 true &#xff1b;否则&#…

AI创作类工具系列之:芝士AI(paperzz)详细测评介绍

学生们&#xff01;又到了写论文的时候~以前以为大家的论文都是一个字一个字敲出来&#xff0c;然后反复修改&#xff0c;熬着大夜改论文。 后来才知道原来大家都会利用工具辅助自己写论文啊&#xff01;今天我就告诉大家一款非常好用的AI写作网站&#xff0c;节省时间&#xf…

代码随想录冲冲冲 Day58 图论Part9

47. 参加科学大会&#xff08;第六期模拟笔试&#xff09; 根据昨天的dijkstra进行堆优化 使用的原因是点多但边少 所以直接对于边进行操作 1.对于priority_queue来说 这是最小堆, 小于的话就是最大堆 之后由于是根据边来说的 所以新建一个Edge并且初始化一下 之后由于使用…

The Open Group 2024生态系统架构·可持续发展年度大会全面解读

在全球数字化转型加速的时代背景下&#xff0c;人工智能技术正以前所未有的速度重塑各行各业的生态系统。尤其是随着ChatGPT、Sora等技术的爆发&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;技术在多个领域展现出超越人类的能力&#xff0c;AGI&#xff08;通用人…

C语言-线程

一,线程的概念 1,线程的定义 在 C 语言中&#xff0c;线程是程序执行的最小单位&#xff0c;它是进程中的一个实体&#xff0c;是被系统独立调度和分派的基本单位。 2、线程的特点 轻型实体&#xff1a;线程是一个轻型实体&#xff0c;它只拥有必不可少的资源&#xff0c;如程…

Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架。它是 Spring 项目家族的一员,用于构建安全的 Java 应用程序。

Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架。它是 Spring 项目家族的一员&#xff0c;用于构建安全的 Java 应用程序。Spring Security 提供了全面的安全服务&#xff0c;从基本的登录认证到复杂的访问控制&#xff0c;几乎涵盖了所有与安全相关的需求…

Paxos 协议详解:分布式系统一致性的基石

文章目录 1. 分布式系统与一致性问题1.1 分布式系统的定义1.2 一致性问题的起源1.3 CAP 定理及其影响1.4 分布式系统中的失败假设 2. Paxos 协议的背景与介绍2.1 Paxos 协议是什么2.3 Paxos 解决什么问题 3. Paxos 的基本原理3.1 Paxos 角色3.2 Paxos 的多数原则3.3 Paxos 协议…

音视频入门基础:FLV专题(1)——FLV官方文档下载

一、FLV简介 Flash Video&#xff08;简称FLV&#xff09;&#xff0c;是一种网络视频格式&#xff0c;用作流媒体格式&#xff0c;它的出现有效地解决了视频文件导入Flash后&#xff0c;使导出的SWF文件体积庞大&#xff0c;不能在网络上有效使用等缺点。 一般FLV文件包在SW…

js删除emoji表情问题

emoji标签占位两个 &#xff0c;直接删除后一位会出现乱码符&#xff1b; 判断是否是emoji function isEmoji(char) {let code char.charCodeAt(0);return code>55296&&code<57343 } // 使用方法&#xff0c;传入单字符 console.log(isEmoji(1)); // false con…

手把手教你找到海外网红合作:海外红人营销渠道

在全球范围内&#xff0c;许多企业寻求与知名网红建立合作关系&#xff0c;以推广产品、共同创作内容或探索其他合作形式。以下是一些有效的方法来实现这一目标&#xff1a; 利用社交媒体平台&#xff1a;社交媒体是寻找海外网红的首选途径。平台如Instagram、YouTube和TikTok拥…

2025届 深圳 嵌入式岗 秋招上岸记录

文章目录 1 背景2 准备阶段2.1 前期2.1.1 掌握的技术栈2.1.2 项目经历2.1.3 比赛&奖学金经历 2.2 中期2.2.1 简历准备2.2.2 个人信息准备2.2.3 企业以及岗位信息的收集2.2.4 个人资料的准备 2.3 简历投递2.3.1 网申2.3.2 招聘会现场投递 3. 简历投递后3.1 测评3.2 笔试3.3 …