一、JWT 与 jjwt

1、JWT 与 jjwt 概述
  1. JWT(JSON Web Token)通常用于身份验证和信息交换

  2. JWT 提供了一种轻量级、自包含的方式来传递用户身份和其他相关信息,同时确保这些信息在传输过程中的安全性和完整性

  3. jjwt 简单而强大的 Java 库,用于创建和验证 JWT,它提供了易于使用的 API,开发者可以轻松地生成和解析 JWT

2、jjwt 引入
  • 在 pom.xml 中引入相关依赖
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.12.6</version>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.12.6</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.12.6</version>
    <scope>runtime</scope>
</dependency>

二、发行时间和过期时间

1、基本介绍
  1. 发行时间和过期时间用于验证 JWT 的有效性

  2. 在使用 jjwt 构建 JWT 时,setIssuedAt 方法和 setExpiration 方法分别用于设置发行时间和过期时间

  3. 不调用 setIssuedAt 方法和 setExpiration 方法,即不设置发行时间和过期时间,JWT 仍然可以被创建,但它将不包含 iat(issued at,发行时间)和 exp(expiration time,过期时间)这两个标准声明

2、演示
准备密钥
private static String SECRET_KEY_STR;
static {
    try {
        KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");

        SecretKey secretKey = keyGen.generateKey();

        SECRET_KEY_STR = Base64.getEncoder().encodeToString(secretKey.getEncoded());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}
(1)设置发行时间和过期时间
String jwt = Jwts.builder()
        .setSubject("user123")
        .setIssuer("MyIssuer")
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY_STR)
        .compact();

System.out.println(jwt);

Claims claims = Jwts.parser()
        .setSigningKey(SECRET_KEY_STR)
        .build()
        .parseClaimsJws(jwt)
        .getBody();

System.out.println("主题:" + claims.getSubject());
System.out.println("发行者:" + claims.getIssuer());
System.out.println("发行时间:" + claims.getIssuedAt());
System.out.println("过期时间:" + claims.getExpiration());
  • 输出结果
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiaXNzIjoiTXlJc3N1ZXIiLCJpYXQiOjE3MzQ5MzgyMjMsImV4cCI6MTczNDk0MTgyM30.eugoVdept39edcpLUAcQ3GGswynl6XgyFxt6qORIxj0
主题:user123
发行者:MyIssuer
发行时间:Mon Dec 23 15:17:03 CST 2024
过期时间:Mon Dec 23 16:17:03 CST 2024
(2)不设置发行时间和过期时间
String jwt = Jwts.builder()
        .setSubject("user123")
        .setIssuer("MyIssuer")
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY_STR)
        .compact();

System.out.println(jwt);

Claims claims = Jwts.parser()
        .setSigningKey(SECRET_KEY_STR)
        .build()
        .parseClaimsJws(jwt)
        .getBody();

System.out.println("主题:" + claims.getSubject());
System.out.println("发行者:" + claims.getIssuer());
System.out.println("发行时间:" + claims.getIssuedAt());
System.out.println("过期时间:" + claims.getExpiration());
  • 输出结果
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiaXNzIjoiTXlJc3N1ZXIifQ.GfZHZRocewWgBRqnolx9sSur9Op9xJVJWZSWWBwgvzY
主题:user123
发行者:MyIssuer
发行时间:null
过期时间:null

三、过期时间验证

1、基本介绍
  1. 对于未过期的 JWT,程序将正常解析

  2. 对于已过期的 JWT,程序将抛出 ExpiredJwtException 异常,建议在解析 JWT 时进行异常处理

2、演示
准备密钥
private static String SECRET_KEY_STR;
static {
    try {
        KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");

        SecretKey secretKey = keyGen.generateKey();

        SECRET_KEY_STR = Base64.getEncoder().encodeToString(secretKey.getEncoded());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}
(1)解析未过期的 JWT
String jwt = Jwts.builder()
        .setSubject("user123")
        .setIssuer("MyIssuer")
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY_STR)
        .compact();

System.out.println(jwt);

Claims claims = Jwts.parser()
        .setSigningKey(SECRET_KEY_STR)
        .build()
        .parseClaimsJws(jwt)
        .getBody();

System.out.println("主题:" + claims.getSubject());
System.out.println("发行者:" + claims.getIssuer());
System.out.println("发行时间:" + claims.getIssuedAt());
System.out.println("过期时间:" + claims.getExpiration());
  • 输出结果
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiaXNzIjoiTXlJc3N1ZXIiLCJpYXQiOjE3MzQ5Mzg4NTMsImV4cCI6MTczNDk0MjQ1M30.ZIGOKo22qbb4iYjOdHjYNcVmi_BtM7b1Kgp9ko7yYwY
主题:user123
发行者:MyIssuer
发行时间:Mon Dec 23 15:27:33 CST 2024
过期时间:Mon Dec 23 16:27:33 CST 2024
(2)解析已过期的 JWT
  1. 对于已过期的 JWT,程序将抛出 ExpiredJwtException 异常
String jwt = Jwts.builder()
        .setSubject("user123")
        .setIssuer("MyIssuer")
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + 1000 * 5))
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY_STR)
        .compact();

System.out.println(jwt);

try {
    Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
    e.printStackTrace();
}

Claims claims = Jwts.parser()
        .setSigningKey(SECRET_KEY_STR)
        .build()
        .parseClaimsJws(jwt)
        .getBody();

System.out.println("主题:" + claims.getSubject());
System.out.println("发行者:" + claims.getIssuer());
System.out.println("发行时间:" + claims.getIssuedAt());
System.out.println("过期时间:" + claims.getExpiration());
  • 输出结果
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiaXNzIjoiTXlJc3N1ZXIiLCJpYXQiOjE3MzQ5Mzg5MzQsImV4cCI6MTczNDkzODkzOX0.rMBwzQrWg8T58GSRupaVZpgySofXd-v5xHtmr4Hqpjs
io.jsonwebtoken.ExpiredJwtException: JWT expired 5967 milliseconds ago at 2024-12-23T07:28:59.000Z. Current time: 2024-12-23T07:29:04.967Z. Allowed clock skew: 0 milliseconds.
  1. 在解析 JWT 时进行异常处理
String jwt = Jwts.builder()
        .setSubject("user123")
        .setIssuer("MyIssuer")
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + 1000 * 5))
        .signWith(SignatureAlgorithm.HS256, SECRET_KEY_STR)
        .compact();

System.out.println(jwt);

try {
    Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
    e.printStackTrace();
}

try {
    Claims claims = Jwts.parser()
            .setSigningKey(SECRET_KEY_STR)
            .build()
            .parseClaimsJws(jwt)
            .getBody();

    System.out.println("主题:" + claims.getSubject());
    System.out.println("发行者:" + claims.getIssuer());
    System.out.println("发行时间:" + claims.getIssuedAt());
    System.out.println("过期时间:" + claims.getExpiration());
} catch (ExpiredJwtException e) {
    System.out.println("JWT 已过期");
} catch (SecurityException e) {
    System.out.println("JWT 签名无效");
}
  • 输出结果
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiaXNzIjoiTXlJc3N1ZXIiLCJpYXQiOjE3MzQ5MzkwMTYsImV4cCI6MTczNDkzOTAyMX0.k85NlFxxk9pxpQj1b0NLEOTcIePzNjNcbk0ai-0_WX4
JWT 已过期

更多推荐