【编码实战】2022年还在用jjwt操作jwt?,推荐你使用nimbus-jose-jwt,爽到飞起~

article/2025/11/9 15:48:58

什么是nimbus-jose-jwt?

nimbus-jose-jwt是基于Apache2.0开源协议的JWT开源库,支持所有的签名(JWS)和加密(JWE)算法。

对于JWT、JWS、JWE介绍

  • JWT是一种规范,它强调了两个组织之间传递安全的信息
  • JWS是JWT的一种实现,包含三部分header(头部)、payload(载荷)、signature(签名)
  • JWE也是JWT的一种实现,包含五部分内容。

在这里插入图片描述

接下来我们将使用对称加密(HMAC)和非对称加密(RSA)两种算法生成和解析JWT令牌。

1.对称加密(HMAC)

对称加密使用相同的密钥进行加密和解密。

  • 首先在pom.xml添加nimbus-jose-jwt依赖库
    <dependencies><!-- web组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.0.RELEASE<version></dependency><!--jwt工具--><dependency><groupId>com.nimbusds</groupId><artifactId>nimbus-jose-jwt</artifactId><version>8.16<version></dependency></dependencies>
  • 创建PayloadDto实体类,用于封装JWT中存储的用户信息;
@Data
@ApiModel("信息实体类")
@Builder
@EqualsAndHashCode(callSuper = false)
public class PayloadDto {@ApiModelProperty("主题")private String sub;@ApiModelProperty("签发时间")private Long iat;@ApiModelProperty("过期时间")private Long exp;@ApiModelProperty("JWT ID")private String jti;@ApiModelProperty("用户名")private String username;@ApiModelProperty("用户权限")private List<String> authorities;
}
  • 创建JwtTokenService接口以及JwtTokenServiceImpl逻辑实现类,在其中添加根据HMAC算法生成和验证令牌方法。
/*** Created by zsh on 2022/3/9*/
public interface JwtTokenService {/*** 使用HMAC对称加密算法生成token*/String generateTokenByHMAC(String payloadStr, String secret) throws KeyLengthException;/*** 模拟生成用户数据*/PayloadDto getDefaultPayloadDto();/*** 验证令牌*/PayloadDto verifyTokenByHMAC(String token, String secret);
}
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.zsh.mall.domain.PayloadDto;
import com.zsh.mall.exception.JwtExpireException;
import com.zsh.mall.exception.JwtInvalidException;
import com.zsh.mall.service.JwtTokenService;
import org.springframework.stereotype.Service;import java.text.ParseException;
import java.util.Date;
import java.util.UUID;/*** Created by zsh on 2022/3/9*/
@Service
public class JwtTokenServiceImpl implements JwtTokenService {@Overridepublic String generateTokenByHMAC(String payloadStr, String secret) {try {//准备JWS-headerJWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.HS256).type(JOSEObjectType.JWT).build();//将负载信息装载到payloadPayload payload = new Payload(payloadStr);//封装header和payload到JWS对象JWSObject jwsObject = new JWSObject(jwsHeader, payload);//创建HMAC签名器JWSSigner jwsSigner = new MACSigner(secret);//签名jwsObject.sign(jwsSigner);return jwsObject.serialize();} catch (KeyLengthException e) {e.printStackTrace();} catch (JOSEException e) {e.printStackTrace();}return null;}@Overridepublic PayloadDto getDefaultPayloadDto() {Date now = new Date();Date exp = DateUtil.offsetSecond(now, 60 * 60);return PayloadDto.builder().sub("zsh").iat(now.getTime()).exp(exp.getTime()).jti(UUID.randomUUID().toString()).username("zsh").authorities(CollUtil.toList("ADMIN")).build();}@Overridepublic PayloadDto verifyTokenByHMAC(String token, String secret) {try {JWSObject jwsObject = JWSObject.parse(token);//创建HMAC验证器JWSVerifier jwsVerifier = new MACVerifier(secret);if (!jwsObject.verify(jwsVerifier)) {throw new JwtInvalidException(401, "token签名不合法!");}String payload = jwsObject.getPayload().toString();PayloadDto payloadDto = JSONUtil.toBean(payload, PayloadDto.class);if (payloadDto.getExp() < new Date().getTime()) {throw new JwtExpireException(401, "token已过期!");}return payloadDto;} catch (ParseException | JOSEException e) {e.printStackTrace();} catch (JwtInvalidException e) {e.printStackTrace();} catch (JwtExpireException e) {e.printStackTrace();}return null;}
}
  • 创建JwtTokenController类,编写依据HMAC算法生成和解析令牌的接口;注意HMAC算法要求密钥的长度至少为32个字节,所以这里我使用了MD5进行了加密充当密钥。
/*** Created by zsh on 2022/3/9*/
@Api(tags = "JwtTokenController", value = "JWT令牌管理")
@RestController
public class JwtTokenController {@Resourceprivate JwtTokenService jwtTokenService;@ApiOperation("使用HMAC对称加密生成token")@GetMapping(value = "/hmac/generate")public CommonResult generateTokenByHMAC() throws KeyLengthException {PayloadDto payloadDto = jwtTokenService.getDefaultPayloadDto();String token = jwtTokenService.generateTokenByHMAC(JSONUtil.toJsonStr(payloadDto), SecureUtil.md5("test"));return CommonResult.success(token);}@ApiOperation("验签")@GetMapping(value = "/hmac/verify")public CommonResult verifyTokenByHMAC(String token) {PayloadDto payloadDto = jwtTokenService.verifyTokenByHMAC(token, SecureUtil.md5("test"));return CommonResult.success(payloadDto);}
}

其他swagger相关的配置和异常类的编写不再展示。

  • 启动访问localhost:8080/swagger-ui.html

在这里插入图片描述
点击测试,发现生成令牌接口正常。
在这里插入图片描述
根据生成的令牌进行解析

在这里插入图片描述
在这里插入图片描述
成功,HMAC对称加密算法生成令牌和解析令牌已经结束!

2.非对称加密(RSA)

非对称加密采用公钥和私钥进行加密和解密。对于加密操作,公钥负责加密,私钥负责解密。对于签名操作,私钥负责签名,公钥负责验签。

对于加密和签名的理解
例如两个端A和B进行通信,A向B发送了一条经过签名和加密的信息;涉及了四个密钥:A公钥、A私钥、B公钥、B私钥。

  • 签名:是为了让B确认这个信息就是A发出的,不是别人
  • 加密:对传输的内容进行保护,即使信息被恶意截取,也无法进行解析。只有B可以查看。

A向B发送信息进行签名和加密的具体流程。

A使用自己的私钥对信息进行签名
A使用B的公钥对信息进行加密

B接收到A发送的信息进行如下处理:

B用自己的私钥对信息进行解密
B使用A的公钥对进行验签操作

所以整个流程保证了端到端的唯一性!

  • 使用JDK提供的keytool工具或者使用git生成jwt.jks,放到resources目录下

在这里插入图片描述

  • 在JwtTokenService接口中定义方法,并在JwtTokenServiceImpl类中实现其业务
    /*** 从类路径下加载jwt.jk*/RSAKey loadJKSByClassPath();/*** 使用RSA非对称算法生成token*/String generateTokenByRSA(String payloadStr, RSAKey rsaKey) throws JOSEException;/*** 根据RSA非对称算法验证token*/PayloadDto verifyTokenByRSA(String token, RSAKey rsaKey) throws ParseException, JOSEException, JwtInvalidException;
	@Overridepublic RSAKey loadJKSByClassPath() {//从类路径下加载证书KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray());KeyPair keyPair = keyStoreKeyFactory.getKeyPair("jwt", "123456".toCharArray());//获取公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();//获取私钥RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();return new RSAKey.Builder(publicKey).privateKey(privateKey).build();}@Overridepublic String generateTokenByRSA(String payloadStr, RSAKey rsaKey) throws JOSEException {//构建JWS头JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT).build();//构建载荷Payload payload = new Payload(payloadStr);//将JWS-header和payload封装成JWS对象中JWSObject jwsObject = new JWSObject(jwsHeader, payload);//创建签名器JWSSigner signer = new RSASSASigner(rsaKey, true);jwsObject.sign(signer);return jwsObject.serialize();}@Overridepublic PayloadDto verifyTokenByRSA(String token, RSAKey rsaKey) throws ParseException, JOSEException, JwtInvalidException {JWSObject jwsObject = JWSObject.parse(token);RSAKey verifyKey = rsaKey.toPublicJWK();JWSVerifier verifier = new RSASSAVerifier(verifyKey);if (!jwsObject.verify(verifier)) {throw new JwtInvalidException(401, "签名不合法!");}String payload = jwsObject.getPayload().toString();String substring = payload.substring(11, payload.length() - 1);String[] strings = substring.split(",");PayloadDto payloadDto = PayloadDto.builder().sub(strings[0]).iat(100L).exp(100L).jti(strings[3]).username(strings[4]).authorities(CollUtil.toList(strings[5])).build();return payloadDto;}
  • 在JwtTokenController中加入以下接口
    @ApiOperation("获取公钥")@GetMapping("/rsa/publicKey")public CommonResult getRsaPublicKey() {RSAKey key = jwtTokenService.loadJKSByClassPath();return CommonResult.success(new JWKSet(key).toJSONObject());}@ApiOperation("使用RSA非对称加密算法生成token")@GetMapping("/rsa/generate")public CommonResult generateTokenByRSA() throws JOSEException {PayloadDto payloadDto = jwtTokenService.getDefaultPayloadDto();RSAKey rsaKey = jwtTokenService.loadJKSByClassPath();String token = jwtTokenService.generateTokenByRSA(payloadDto.toString(), rsaKey);return CommonResult.success(token);}@ApiOperation("RSA验签")@GetMapping("/rsa/verify")public CommonResult verifyTokenByRSA(String token) throws ParseException, JOSEException, JwtInvalidException {PayloadDto payloadDto = jwtTokenService.verifyTokenByRSA(token, jwtTokenService.loadJKSByClassPath());return CommonResult.success(payloadDto);}
  • 测试
    在这里插入图片描述
    在这里插入图片描述

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

相关文章

什么是JWT??

一、什么是JWT JWT(JSON WEB TOKEN)&#xff0c;通过数字签名的方式&#xff0c;以json对象为载体&#xff0c;在不同的服务终端之间安全的传输信息&#xff0c;用来解决传统session的弊端。 JWT在前后端分离系统&#xff0c;或跨平台系统中&#xff0c;通过JSON形式作为WEB应用…

JJWT实现令牌Token

登录实现方式 Session 详情&#xff1a; https://www.cnblogs.com/andy-zhou/p/5360107.html 会话的概念 会话就好比打电话&#xff0c;一次通话可以理解为一次会话。我们登录一个网站&#xff0c;在一个网站上不同的页面浏览&#xff0c;最后退出这个网站&#xff0c;也是…

3.JJWT

目录 1.JWT简介 2.JWT的结构 3.基于服务器的传统身份认证 4.基于token的身份认证 5. JWT的优势 6.Java中使用JJWT实现JWT 1.JWT简介 Json web token (JWT)&#xff0c; 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519)。该token被设计为紧凑且安全的…

JWT技术

JWT 一、 JWT 实现无状态 Web 服务 1、什么是有状态 有状态服务&#xff0c;即服务端需要记录每次会话的客户端信息&#xff0c;从而识别客户端身份&#xff0c;根据用户身份进行请求的处理&#xff0c;典型的设计如tomcat中的session。 例如登录&#xff1a;用户登录后&am…

token学习笔记(JWT、jjwt的使用及案例实现)

文章目录 1. 首先、了解什么是会话2. 会话跟踪的主要技术3. Token 令牌学习3.1 流程图3.2 token3.3 JWT(JSON web Tokens)Json web 令牌(规范)3.4 JWT结构3.5 JWT需要的依赖3.6 JWT的获取与验证流程3.7JWT的使用方式3.8 jjwt的使用&#xff08;创建JWT方式&#xff09;1. jjwt需…

JWT 进阶 -- JJWT

###jwt是什么? JWTs是JSON对象的编码表示。JSON对象由零或多个名称/值对组成&#xff0c;其中名称为字符串&#xff0c;值为任意JSON值。JWT有助于在clear(例如在URL中)发送这样的信息&#xff0c;可以被信任为不可读(即加密的)、不可修改的(即签名)和URL - safe(即Base64编码…

JWT详解和使用(jjwt)

JWT详解和使用 JWT是啥 JWT&#xff08;JSON Web Token&#xff09;是一个开放标准(RFC 7519)&#xff0c;它定义了一种紧凑的、自包含的方式&#xff0c;用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任&#xff0c;因为它是数字签名的。 下列场景中使用…

JJWT 实现JWT

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

什么是JWT?

在HTTP接口调用的时候&#xff0c;服务端经常需要对调用方做认证&#xff0c;以保证安全性。一种常见的认证方式是使用JWT(Json Web Token)&#xff0c;采用这种方式时&#xff0c;经常在header传入一个authorization字段&#xff0c;值为对应的jwt_token&#xff0c;或者也有图…

JWT的学习和JJWT的使用

1.什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一个开放的行业标准&#xff0c;它定义了一种简介的&#xff0c;自包含的协议格式&#xff0c;用于在通信双方传递json对象&#xff0c;传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或者使用RSA的公…

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…