JWT的学习和JJWT的使用

article/2025/11/9 15:57:13

1.什么是JWT

JWT(JSON Web Token)是一个开放的行业标准,它定义了一种简介的,自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或者使用RSA的公钥/私钥对来进行签名,防止被篡改。

官网: https://jwt.io/

JWT令牌的优点:

  • jwt基于json,非常方便进行解析
  • 可以在令牌中自定义丰富的内容,更容易进行扩展
  • 通过非对称加密算法和数字签名技术,JWT防止篡改,安全性高

JWT令牌的缺点:

  • JWT令牌较长,所占的存储空间比较大。

2.JWT的组成

一个JWT实际就是一个字符串,它由三部分组成:头部,载荷,签名

2.1JWT的头部(Header)

头部用于描述关于该JWT的最基本信息,例如其类型(即JWT)以及签名所用的算法(HMAC,SHA256,RSA)等等

{"alg":"HS256""typ":"JWT"
}
  • alg:表示签名使用的算法
  • typ:类型

我们对头部的json字符串进行BASE64编码后就能得到一个字符串,JDK中提供了非常方便的BASE64EncoderBASE64Decoder,用它们可以非常方便的完成基于BASE64的编码和解码。

2.2载荷(Payload)

第二部分的内容是载荷,就是存放有效信息的地方,这些有效信息包含三个部分

  1. 标准中注册的声明(建议但不强制使用)

    iss: jwt的签发者
    sub: jwt所面向的用户
    aud: 接收jwt的一方
    exp: jwt的过期时间,这个过期时间必须大于签发时间
    iat: jwt的签发时间
    nbf: 定义在什么时间之前,这个jwt都是不可用的
    jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
    
  2. 公共的声明

    ​ 公共的声明可以添加任何的信息,一般添加用户的相关信息或者其他业务需要的必要信息, 但不建议添加敏感的信息,因为载荷可以解密。

  3. 私有的声明

    ​ 私有声明是提供者和消费者所共同定义的声明,一般还是不建议存放敏感的信息,因为base64是对称解密的,意味着这一部分的信息可以归类为明文信息。

自定义claim,比如下面例子中的name就属于自定义的claim。这些claim跟JWT标准规定的claim区别在于:JWT规定的claim在接收方拿到JWT后,都知道怎么对标准的claim进行验证,而私有的claim不会验证,除非明确告诉接收方要对这些claim进行验证以及验证的规则才行。

{"sub":"2390866852","name":"Test","iat":"12312323"
}

上面的name是自定义的声明(公共的或者私有的),而另外两部分是标准的声明

2.3签证,签名(signature)

jwt的第三部分是一个签证的信息,这个签证信息由三部分组成:

  1. header(base64编码后的)
  2. payload(base64编码后的)
  3. secret(盐,一定要保密)

​ 这个部分需要base64加密后的header和payload使用**.**连接组成的字符串,然后通过header中声明的加密模式进行加盐secret组合加密,形成一个完整的签证

将这三个部分用 . 连接拼成一个完整的字符串,也就是最终的jwt

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来对jwt的签发和验证,所以它就是你服务端的私钥,在任何的场景中都不应该泄露出去,一旦客户端得知了你的盐,那就意味着客户端可以进行自我的签发jwt。

3.JJWT快速使用

jjwt是jwt在java中的主流应用,下面将实现一个demo进行学习

新建第一个springboot的项目进行测试

pom.xml

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>

3.1创建token

    /*** 创建token*/@Testpublic void testCreateToken() {//创建JwtBuilder对象JwtBuilder jwtBuilder = Jwts.builder()//声明的唯一标识{"jti":"6666"}.setId("6666")//主体,面向的用户{"sub":"Test"}.setSubject("Test")//签发时间{"iat":"xxxxx"}.setIssuedAt(new Date())//签证.signWith(SignatureAlgorithm.HS256, "scret");//获取jwt的tokenString token = jwtBuilder.compact();System.out.println(token);System.out.println("======================");String[] split = token.split("\\.");//头部System.out.println(Base64Codec.BASE64.decodeToString(split[0]));//载荷System.out.println(Base64Codec.BASE64.decodeToString(split[1]));//盐,无法解析System.out.println(Base64Codec.BASE64.decodeToString(split[2]));}

3.2解析token

    /*** 解析token*/@Testpublic void testParesToken() {String token = "eyJhbGciOiJIUzI1NiJ9." +"eyJqdGkiOiI2NjY2Iiwic3ViIjoiVGVzdCIsImlhdCI6MTY2MzIxMTA3Mn0." +"BcbZ2T_kmFg94-L3z1TXCCEDln1qwX-F9cPs9WiK8Fc";//解析token获取负载中声明的对象Claims claims = Jwts.parser().setSigningKey("scret").parseClaimsJws(token).getBody();System.out.println("id:" + claims.getId());System.out.println("sub:" + claims.getSubject());System.out.println("issuedAt:" + claims.getIssuedAt());}

运行解析token得到如下结果:

在这里插入图片描述

3.3创建有失效时间的token

    /*** 创建token(失效时间)*/@Testpublic void testCreateTokenHasExp() {//当前系统时间long now = System.currentTimeMillis();//失效时间(当前系统时间+1分钟)long exp = now + 60 * 1000;//创建JwtBuilder对象JwtBuilder jwtBuilder = Jwts.builder()//声明的唯一标识{"jti":"6666"}.setId("6666")//主体,面向的用户{"sub":"Test"}.setSubject("Test")//签发时间{"iat":"xxxxx"}.setIssuedAt(new Date())//签证.signWith(SignatureAlgorithm.HS256, "scret")//失效时间{"exp":"xxxxx"}.setExpiration(new Date(exp));//获取jwt的tokenString token = jwtBuilder.compact();System.out.println(token);System.out.println("======================");String[] split = token.split("\\.");//头部System.out.println(Base64Codec.BASE64.decodeToString(split[0]));//载荷System.out.println(Base64Codec.BASE64.decodeToString(split[1]));//盐,无法解析System.out.println(Base64Codec.BASE64.decodeToString(split[2]));}

3.4解析有失效时间的token

    /*** 解析token(失效时间)*/@Testpublic void testParesTokenHasExp() {String token = "eyJhbGciOiJIUzI1NiJ9." +"eyJqdGkiOiI2NjY2Iiwic3ViIjoiVGVzdCIsImlhdCI6MTY2MzIxMjEwMiwiZXhwIjoxNjYzMjEyMTYyfQ." +"PKH59MVUuwmkBWTw7cCN3L3eg_atHaCGwuoe5wNQbJs";//解析token获取负载中声明的对象Claims claims = Jwts.parser().setSigningKey("scret").parseClaimsJws(token).getBody();System.out.println("id:" + claims.getId());System.out.println("sub:" + claims.getSubject());System.out.println("issuedAt:" + claims.getIssuedAt());SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("签发时间:" + simpleDateFormat.format(claims.getIssuedAt()));System.out.println("过期时间:" + simpleDateFormat.format(claims.getExpiration()));System.out.println("当前时间:" + simpleDateFormat.format(new Date()));}

当设置的token已经失效后,会出现如下错误:

在这里插入图片描述

3.5创建自定义token

    /*** 创建token(自定义)*/@Testpublic void testCreateTokenByClaims() {//创建JwtBuilder对象JwtBuilder jwtBuilder = Jwts.builder()//声明的唯一标识{"jti":"6666"}.setId("6666")//主体,面向的用户{"sub":"Test"}.setSubject("Test")//签发时间{"iat":"xxxxx"}.setIssuedAt(new Date())//签证.signWith(SignatureAlgorithm.HS256, "scret")//自定义声明.claim("role", "admin").claim("info", "top");//获取jwt的tokenString token = jwtBuilder.compact();System.out.println(token);System.out.println("======================");String[] split = token.split("\\.");//头部System.out.println(Base64Codec.BASE64.decodeToString(split[0]));//载荷System.out.println(Base64Codec.BASE64.decodeToString(split[1]));//盐,无法解析System.out.println(Base64Codec.BASE64.decodeToString(split[2]));}

3.6解析自定义token

    /*** 解析token(自定义)*/@Testpublic void testParesTokenByClaims() {String token = "eyJhbGciOiJIUzI1NiJ9." +"eyJqdGkiOiI2NjY2Iiwic3ViIjoiVGVzdCIsImlhdCI6MTY2MzIxMjUxNCwicm9sZSI6ImFkbWluIiwiaW5mbyI6InRvcCJ9." +"v69wR_j8HXXto0A5QPl6paQDZaHSrBwZ-QZtTwvi6dw";//解析token获取负载中声明的对象Claims claims = Jwts.parser().setSigningKey("scret").parseClaimsJws(token).getBody();System.out.println("id:" + claims.getId());System.out.println("sub:" + claims.getSubject());System.out.println("issuedAt:" + claims.getIssuedAt());System.out.println("role:" + claims.get("role"));System.out.println("info:" + claims.get("info"));}

解析自定义token信息出现如下结果:

在这里插入图片描述

以上就是在java中对jwt的简单使用,完整源代码在gitee仓库!


http://chatgpt.dhexx.cn/article/DhPcer7M.shtml

相关文章

JWT详解

本文从本人博客搬运&#xff0c;原文格式更加美观&#xff0c;可以移步原文阅读&#xff1a;JWT详解 JWT简介 1.什么是JWT 在介绍JWT之前&#xff0c;我们先来回顾一下利用token进行用户身份验证的流程&#xff1a; 客户端使用用户名和密码请求登录服务端收到请求&#xff…

JWT详解、JJWT使用、token 令牌

前言 在正式讲解JWT之前&#xff0c;我们先重温一下用户身份认证相关的一些概念&#xff1a; 有状态登录&#xff08;session认证&#xff09; 服务器当中记录每一次的登录信息&#xff0c;从而根据客户端发送的数据来判断登录过来的用户是否合法。 缺点&#xff1a; 每个用…

Java的JJWT实现JWT

1 什么是 JJWT JJWT 是一个提供端到端的 JWT 创建和验证的 Java 库。永远免费和开源 (Apache License&#xff0c;版本2.0)&#xff0c;JJWT 很容易使用和理解。它被设计成一个以建筑为中心的流畅界面&#xff0c;隐藏了它的大部分复杂性。 2 token 的创建 2.1 引入依赖 &l…

解决Red Hat虚拟机与主机网络不通

虚拟机版本&#xff1a;Red Hat Enterprise Linux 7 64 位 安装&#xff1a;自定义安装&#xff0c;带GUI的服务器&#xff0c;创建图形化界面 创建完毕后发现网络ping不通&#xff0c;经过查阅各种资料&#xff0c;在同事的帮助下终于解决。做一个记录。 1、VMware网络配置。…

虚拟机VMware和宿主机连接

文章目录 一、NAT连接1.查看宿主机IP地址2.设置VMnet8信息2.设置虚拟机模式3.设置虚拟网络4.设置虚拟机内系统IP&#xff08;Centos8.2为例&#xff09;4.1.图形化操作4.1.1DHCP4.1.2静态IP4.1.3 重启网卡&#xff08;修改网卡信息后&#xff09; 5.测试5.1.宿主机ping虚拟机5.…

VMware虚拟机三种网络连接模式详解

VMware虚拟机三种网络连接模式详解 Vmware提供了三种网络工作模式&#xff0c;分别是&#xff1a;&#xff08;1&#xff09;Bridged&#xff08;桥接模式&#xff09;&#xff1b;&#xff08;2&#xff09;NAT&#xff08;网络地址转换模式&#xff09;&#xff1b;&#xf…

虚拟机与主机之间通信

1.bridged(桥接方式&#xff0c;默认使用vmnet0虚拟网卡)&#xff1a; 选择这种模式&#xff0c;虚拟机等同于网络内的一台物理主机&#xff0c;可对手动设置IP&#xff0c;子网掩码。DNS&#xff0c;且IP地址要和主机的IP在同一网段内。这样。虚拟机就和主机如同连在一个HUB上…

虚拟机的几种网络连接方式

系列运维 文章目录 系列运维前言一、几种网络连接方式各是什么&#xff1f;二、网络连接的差异性总结 前言 VirtualBox中有4种网络连接方式&#xff1a; NAT Bridged Adapter Internal Host-only Adapter VMWare中有三种&#xff0c;VirtualBox只是比VMWare多了Internal方式。…

主机、虚拟机、开发板之间网络连接设置

最近在玩开发板&#xff0c;主机使用的无线网卡&#xff0c;开发板与主机网线直连&#xff0c;现在开发板想使用tftp直接从虚拟机下载镜像等文件&#xff0c;偶尔又需要虚拟机从主机下载文件&#xff0c;虚拟机有时候又需要网络&#xff0c;经过一番折腾算是调试成功。 1.主机…

vmware虚拟机与主机共享网络

我的虚拟机总是各种连不上网&#xff0c;每次都要折腾一番。现在我把虚拟机连不上网的原因总体排查一下&#xff0c;按照流程一步步来&#xff0c;基本上可以解决大部分人的问题。 首先&#xff0c;在VMware的编辑->虚拟网络编辑器重新建立&#xff2e;&#xff21;&#xf…

Virtualbox虚拟机与主机相互访问

刚从vmware切换到Virtualbox有些地方还是不太熟悉。网络连接这块就被卡了一下&#xff0c;后来发现其实很简单&#xff0c;是我想多了。 环境 主机&#xff1a; archlinux 虚拟机&#xff1a;windows 10 软件版本&#xff1a;VirtualBox 6.1 理论上这些环境不影响&#xff0…

虚拟机和主机无法连接

vm网络配置&#xff1a;https://www.cnblogs.com/aeolian/p/8882790.html 一、首先查看自己的虚拟机服务有没有开启&#xff0c;选择电脑里面的服务查看&#xff1b; 1.计算机点击右键选择管理 2.进入管理选择VM开头的服务如果没有开启的话就右键开启 二、虚拟机服务开启后就…

虚拟机和主机的网络访问

本人的问题是主机可以ping虚拟机&#xff0c;虚拟机可以正常访问端口&#xff0c;主机不能访问虚拟机端口&#xff0c;然后就进行各种问题的排查&#xff0c;一开始把所有的防火墙都关了还不行&#xff0c;所以来到了windows主机虚拟网卡这里设置&#xff0c;使用了手动设置虚拟…

VMwareWorkstationPro虚拟机与主机远程连接

目录 一 &#xff0c;虚拟机与主机远程连接环境设置 二 虚拟机与主机远程连接 一 &#xff0c;虚拟机与主机远程连接环境设置 1 点击设置打开系统选项 2 打开远程控制 3 点击设置打开更新和安全 4 关闭病毒防护和防火墙 &#xff08;注&#xff1a;主机与虚拟机都要执行…

ubutu虚拟机和主机共享同一网络

ubutu虚拟机和主机共享同一网络 前言一、使用场景二、vmware设置三、主机windows设置四、虚拟机ubuntu配置 前言 ​ 本文采用的是共享同一网卡的方式达到虚拟机使用和主机一样的网络的目的。主要参考了虚拟机共享主机网卡连接的第一部分内容&#xff0c;感兴趣的朋友可以去大佬…

虚拟机三种网络连接方式

第一种连接方式-桥接模式 原理图&#xff1a; 桥接模式效果&#xff1a;通过桥接&#xff0c;我们让vm虚拟机和真正主机pc3处在了一片局域网下&#xff0c;vm虚拟机可以访问pc123也可以外网&#xff08;Internet)&#xff0c;同时pc123也可以访问vm虚拟机。好处是vm虚拟机可以…

VMware 虚拟机与主机网络互通

VMware连接网络 一、虚拟机服务开启二、本地网络虚拟机的网卡启动三、设置虚拟机四、IPv4设置 一、虚拟机服务开启 1.右击“此电脑”图标&#xff0c;单击“管理”&#xff0c;出现以下界面。 查看VMware是否开启&#xff0c;没有开启的话&#xff0c;就右击→“启动”。 二…

虚拟机仅主机连接模式设置

系统——网络连接 上面输入的地址通过命令ipconfig在本地查到的VMnet1对应的Ipv4地址即可&#xff0c;一般默认网关前三位和地址的一样&#xff0c;最后一个为1&#xff0c;即***.***.***.1 最后设置虚拟接的选项 这样仅主机模式就设置好了&#xff0c;设置了之后&#xff0c;虚…

VMware Workstations 虚拟机和主机网络配置

在Windows上安装虚拟机&#xff0c;是在学习使用Linux时的常用手段&#xff0c;在当我们安装好虚拟机之后&#xff0c;怎么配置虚拟机和物理机直接的网络通信呢&#xff0c;这里以Ubuntu系统为例 先简单描述一下NAT和桥接 在安装虚拟机的时候&#xff0c;一般来说&#xff0c;…

Linux 虚拟机和主机互通 [万能方法]

VMware Linux 虚拟机和主机互通 [万能方法] 前言&#xff1a;诸如以下问题&#xff0c;解决问题的思路都是一样的&#xff0c;看完此文后都能找到答案&#xff1a; 主机为何 ping 不通 虚拟机&#xff1f;请检查是否在同一网段&#xff1f;Linux 防火墙是否为开启状态&#x…