Jjwt详解

Posted by Wh0ami-hy on October 13, 2023

1. 引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.12.3</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.12.3</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
    <version>0.12.3</version>
</dependency>

或者

<dependency>  
    <groupId>io.jsonwebtoken</groupId>  
    <artifactId>jjwt</artifactId>  
    <version>0.12.3</version>  
</dependency>

2. 生成JWT

指定签名算法并生成密钥(signing key)

SecretKey key = Jwts.SIG.HS256.key().build();

生成JWT,设置完各项参数后,使用.compact()生成JWT

public static String generateToken(String username) {  
    Date now = new Date();  
    Date expiration = new Date(now.getTime() + 360000);  
    String jwt = Jwts.builder()  
            .header()  
                .and()  
            .expiration(expiration)  
            .signWith(key)  
            .subject(username)  
            .compact();  
  
    return jwt;  
}

3. 配置JWT header

3.1. JwtBuilder.header()

JwtBuilder 的header()方法,配置完header后,调用.and() 表明header配置完成,返回到JwtBuilder,再去配置payload等

and相当于结束符,表示结束当前标签

String jwt = Jwts.builder()
        
    .header()                        // <----
        .keyId("aKeyId")
        .x509Url(aUri)
        .add("someName", anyValue)
        .add(mapValues)
        // ... etc ...
        .and()                      // go back to the JwtBuilder
        
    .subject("Joe")                 // resume JwtBuilder calls...
    // ... etc ...    
    .compact();

你不需要设置alg、enc或zip标头——JJWT总是会根据需要自动设置它们

JwtBuilder.header()下的.add()方法支持键值对

3.2. Jwts.header()

如果你想在使用JwtBuilder的上下文中创建一个独立的header,可以直接使用Jwts.header(),最后使用.build()生成一个Header实例

Header commonHeader = Jwts.header() 

        .keyId("aKeyId")
        .x509Url(aUri)
        .add("someName", anyValue)
        .add(mapValues)
        // ... etc ...
        
        .build()  // <---- not 'and()'

这种方式适用于需要提取公共header参数的JWT,该公共header可被任意JwtBuilder使用

String jwt = Jwts.builder()

    .header()
        .add(commonHeader)                   // 将上面创建的公共header引入
        .add("specificHeader", specificValue) // jwt-specific headers...

    .subject("whatever")
    // ... etc ...
    .compact();

4. 配置JWT Payload

JWT Payload 可以是任何东西——任何可以表示为字节数组的东西,比如文本、图像、文档等等。

JwtBuilder 支持两种不同的JWT Payload选项

  • content JWT Payload 是任意字节数组
  • claims JWT Payload 是一个JSON声明对象

注意:content和claims不能同时使用

4.1. 任意字节数组

Jwts.builder().content(content, "text/plain")方法,.content()方法有两个参数,第一个参数是实际的字节数组,第二个参数是媒体类型的字符串标识符

常见的有

  • text/html HTML格式
  • text/plain 纯文本格式
  • text/ xml XML格式
  • image/ jpeg jpg图片格式
  • image/png png图片格式
byte[] content = "Hello World".getBytes(StandardCharsets.UTF_8);

String jwt = Jwts.builder()

    .content(content, "text/plain") // <---
    
    .build();

4.2. JSON声明对象

标准的(官方提供的7个字段)

  • issuer: sets the iss (Issuer) Claim
  • subject: sets the sub (Subject) Claim
  • audience: sets the aud (Audience) Claim
  • expiration: sets the exp (Expiration Time) Claim
  • notBefore: sets the nbf (Not Before) Claim
  • issuedAt: sets the iat (Issued At) Claim
  • id: sets the jti (JWT ID) Claim

String jws = Jwts.builder()

    .issuer("me")
    .subject("Bob")
    .audience("you")
    .expiration(expiration) //a java.util.Date
    .notBefore(notBefore) //a java.util.Date 
    .issuedAt(new Date()) // for example, now
    .id(UUID.randomUUID().toString()) //just an example id
    

自定义的

自定义单个增加字段,调用JwtBuilderclaim 方法

String jws = Jwts.builder()

    .claim("hello", "world")
    .claim("teacher", "good")

自定义批量增加字段,调用JwtBuilder 的claims(Map)方法,claims()方法中的参数是一个map类型

String jws = Jwts.builder()

    .claims(Map)
    
    // ... etc ...

5. 为JWT签名

JWT规范确定了13个标准签名算法——3个秘密密钥算法和10个非对称密钥算法

生成密钥SecretKey,使用Jwts.SIG方法

SecretKey key = Jwts.SIG.HS256.key().build(); //or HS384.key() or HS512.key()

使用signWith()签名

String jws = Jwts.builder()
	.subject("Joe")
	.signWith(key)
	.compact();

6. 解析JWT

使用Jwts.parser()方法创建一个 JwtParserBuilder ,可以调用.keyLocator().verifyWith() , .decryptWith() 方法去解析JWT中的信息

需要注意parser()下调用的方法应该放在 try/catch代码块中执行

public static String getClaimsByToken(String token) {  
    try{  
        Claims claim = Jwts.parser()  
                .verifyWith(key)  
                    // or .keyLocator(keyLocator) dynamically locate signing or encryption keys
				    // or .decryptWith(key)   a constant key used to decrypt all encrypted JWTs
                .build()  // 结束 parser
                .parseSignedClaims(token)  // or parseSignedClaims, parseEncryptedClaims, parseSignedContent, parse
                .getPayload();  
        return claim.toString();  
  
    }catch (JwtException e){  
        System.out.println(e.getStackTrace());  
        return null;  
    }  
}

本站总访问量