JJWT使用完全指南

JJWT使用完全指南JJWT 是一款适用于 Java 和 Android 的 JSONWebToken JWT 库

大家好,欢迎来到IT知识分享网。

JJWT的优点

  • 功能齐全
  • 安全
  • 流式接口开发,方便,可读性强。在IDE中有自动补全代码的功能
  • 完全符合RFC规范
  • 100%的代码测试覆盖率
  • 使用所有标准JWS算法创建、解析和验证数字签名的紧凑JWT

JJWT 签名算法

标示符 签名算法
HS256 使用SHA-256的HMAC
HS384 使用SHA-384的HMAC
HS512 使用SHA-512的HMAC
ES256 使用P-256 和SHA-256的ECDSA
ES384 使用P-384 和SHA-384的ECDSA
ES512 使用P-512 和SHA-512的ECDSA
RS256 使用SHA-256的RSASSA-PKCS-v1_5
RS384 使用SHA-384的RSASSA-PKCS-v1_5
RS512 使用SHA-512的RSASSA-PKCS-v1_5
PS256 SHA-256 和MGF1 with SHA-256 的RSASSA-PSS
PS384 RSASSA-PSS using SHA-384 and MGF1 with SHA-384
PS512 RSASSA-PSS using SHA-512 and MGF1 with SHA-512
EdDSA Edwards-curve Digital Signature Algorithm
  • HMAC(Hash-based Message Authentication Code)是一种基于哈希函数的消息认证码算法。它使用一个密钥以及输入的消息作为输入,通过执行特定的哈希函数运算,生成一个长度固定的认证码。HMAC可以用于验证消息的完整性和验证消息的来源身份。
  • 使用所有标准JWE加密算法创建、解析和解密加密的紧凑JWT
  • 用于获取JWE加密和解密密钥的所有密钥管理算法
  • 使用本地Java密钥类型以所有标准JWA密钥格式创建、解析和验证JSON Web密钥(JWK)

JJWT依赖导入

在项目的pom.xml 添加如下配置:

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>JJWT_RELEASE_VERSION</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>JJWT_RELEASE_VERSION</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred --> <version>JJWT_RELEASE_VERSION</version> <scope>runtime</scope> </dependency> 
  • JJWT_RELEASE_VERSION 对应JJWT的发布版本,目前最新版本是0.11.5,关于JJWT的发布版本, 可以参考:https://github.com/jwtk/jjwt/tags
  • 因为JWT是以JSON格式进行数据的传递, 这里使用的JOSN包是jackson,如果要使用Gson的JSON包,可以导入 jjwt-gson

如果有以下使用场景,需要额外导入 bcprov-jdk15on 的库

  • JDK 10或更早的版本, 需要使用RSASSA-PSS (PS256, PS384, PS512) 签名算法
  • JDK 10或更早的版本, 需要使用EdECDH(X25519 或 X448)椭圆曲线 Diffie-Hellman 加密。
  • JDK14或更早版本, 需要使用EdDSA (Ed25519 or Ed448) 椭圆曲线签名算法
    注意:如果是JDK15及之后的版本, 则不需要添加
 <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> <scope>runtime</scope> </dependency> 

为什么jjwt-impl 的scope是runtime

JJWT 保证除 jjwt-impl .jar 之外的所有工件的语义版本控制兼容性。 对于 jjwt-impl .jar 没有这样的保证,并且该 .jar 中的内部更改可能随时发生。 切勿将 jjwt-impl .jar 添加到具有编译范围的项目中 – 始终使用运行时范围声明它。

JJWT示例

有签名的JWT令牌:

 @Test public void genJws() { //1. 产生令牌 SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //HMAC-SHA-256 String jws = Jwts.builder().setSubject("Osxm").signWith(key).compact(); System.out.println("jws="+jws); //2. 解析令牌 String str = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jws).getBody().getSubject(); System.out.println(str); } 
  • 签名的JWT, 如果在解析的时候没有设置签名key会提示如下错误: java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed.
  • 所以 ,可以通过异常捕获判断是否是有效的签名token 。

设置 JWT 头部

 @Test public void setHeader() { SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); String jws = Jwts.builder() .setHeaderParam("head1", "head1 value") .setHeaderParam("head2", "head2 value") .setSubject("Osxm").signWith(key).compact(); System.out.println("jws="+jws); } 

负载

设置普通的文本

String jwt = Jwts.builder().setPayload("普通文本的负载").compact(); 

JWT 有效负载可能包含 JWT 接收者的断言或声明,而不是内容字节数组。 在这种情况下,有效负载是声明 JSON 对象,并且 JJWT 支持使用类型安全构建器方法创建声明。

 @Test public void payload() { Date now = new Date(); String jwt = Jwts.builder().setPayload("普通文本的负载").compact(); Jwts.builder() .setIssuer("Osxm") .setSubject("Demo JWT") .setAudience("ITs") .setExpiration(new Date(now.getTime() + 3600 * 1000)) //过期时间, 1小时 .setNotBefore(now) //最早生效时间 .setIssuedAt(now) .setId(UUID.randomUUID().toString()) .compact(); } 
  • JSON Web Tokens(JWT)中,“notBefore”(nbf)是一个标准声明,代表了令牌在此之前不被视为有效。它指示令牌可以开始使用或接受的最早时间(以秒或特定日期和时间表示)。

增加其他的声明:

.claim("myname", "myvalue") 

签名密钥

签名密钥

用公钥签署 JWT不安全。 JJWT 将拒绝任何指定的 PublicKey 进行签名,并抛出 InvalidKeyException。

JWE – 完全加密的JWT

根据密钥的不同格式,

  • 编码的字节数组:  SecretKey key = Keys.hmacShaKeyFor(encodedKeyBytes);
  • Base 64编码字符串: SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));
  • Base64URL 编码的字符串:SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(secretString));
  • 原始(未编码)字符串(例如密码字符串):SecretKey key = Keys.hmacShaKeyFor(secretString.getBytes(StandardCharsets.UTF_8));

注意: secretString.getBytes() (不提供字符集)的方式是不推荐的。此外使用原始密码字符串,不可避免地会导致钥匙脆弱或敏感, 尽量使用安全随机密钥。

@Test public void key() { //1. 方式1 ,使用密码字符串的字节数组 String mykeyString = "thisismykeythisismykeythisismykeythisismykey"; Key secretKey = Keys.hmacShaKeyFor(mykeyString.getBytes(StandardCharsets.UTF_8)); //2. 使用Java本身获取 Key secretKey2 = new SecretKeySpec(mykeyString.getBytes(StandardCharsets.UTF_8),"HmacSHA256"); //3. JJWT的SignatureAlgorithm Key secretKey3 = new SecretKeySpec(mykeyString.getBytes(StandardCharsets.UTF_8), SignatureAlgorithm.HS256.getJcaName()); //4. 随机字符串 Key secretKey4 = Keys.secretKeyFor(SignatureAlgorithm.HS256); String keyString = Encoders.BASE64.encode(secretKey4.getEncoded()); System.out.println("keyString="+keyString); } 

JWT压缩

读取 JWT

 Jws<Claims> jws = Jwts.parserBuilder().setSigningKey(mykeyString.getBytes(StandardCharsets.UTF_8)).build().parseClaimsJws(jwsString); String issuer = jws.getBody().getIssuer(); System.out.println("issuer="+issuer); 
 // 创建JWT解析器,并设置签名密钥解析器 JwtParser jwtParser = Jwts.parserBuilder() .setSigningKeyResolver(new SigningKeyResolverAdapter() { @Override public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { // 在这里实现自定义的签名密钥解析逻辑,并返回解析的密钥 // ... } }) .build(); // 使用解析器解析JWT Jws<Claims> jws = jwtParser.parseClaimsJws(jwt); Claims claims = jws.getBody(); 


免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/113858.html

(0)
上一篇 2025-12-12 11:10
下一篇 2025-12-12 11:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信