JJWT

作者: 又语 | 来源:发表于2020-04-16 19:44 被阅读0次

本文介绍基于 jjwt 的 JWT 实现方法。


目录

  • jjwt 简介
  • 代码示例

jjwt 简介

JJWT 是完全基于 JWT、JWS、JWE、JWK 和 JWA RFC 规范的 Java 实现,采用 Apache License 2.0 开源协议。

JJWT 支持的算法:

  • HS256: HMAC using SHA-256
  • HS384: HMAC using SHA-384
  • HS512: HMAC using SHA-512
  • ES256: ECDSA using P-256 and SHA-256
  • ES384: ECDSA using P-384 and SHA-384
  • ES512: ECDSA using P-521 and SHA-512
  • RS256: RSASSA-PKCS-v1_5 using SHA-256
  • RS384: RSASSA-PKCS-v1_5 using SHA-384
  • RS512: RSASSA-PKCS-v1_5 using SHA-512
  • PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
  • PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
  • PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512

PS256PS384PS512 需要 JDK 11 或合适的 JCA 供应商(如:BouncyCastle)

JJWT 还添加了一些规范外的方便扩展,包括:

  • JWT Body 压缩,不只是 JWEs
  • Claims 断言(需要指定值)
  • 使用合适的 JSON 解析器完成 Claim POJO 的序列化和反序列化
  • 基于期望的 JWA 算法的安全密钥生成

目前为止尚不支持的特性:

  • JWE (JWT 加密)

代码示例

  1. 添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>java-tutorial</artifactId>
        <groupId>tutorial.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <properties>
        <jackson.version>2.10.3</jackson.version>
    </properties>

    <artifactId>jwt-tutorial</artifactId>
    <dependencies>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.1</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.1</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.1</version>
            <scope>runtime</scope>
        </dependency>
        <!-- JDK 10 及之前版本需要添加 bcprov-jdk15on 依赖 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.60</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  1. 编写代码
package tutorial.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.junit.Assert;
import org.junit.Test;

import java.security.Key;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

public class JjwtTest {

    @Test
    public void test() {
        // 生成签名密钥,通常密钥应该从应用配置中读取
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        String issuer = "Issuer";
        String subject = "Subject";
        // JWS 是签名后的 JWT
        String jws = Jwts.builder()
                .setIssuer(issuer)
                .setExpiration(date(2020, 6, 30, 23, 59, 59))
                .setSubject(subject)
                .setAudience("Audience X")
                .setNotBefore(date(2020, 1, 1, 0, 0, 0))
                .setIssuedAt(date(2020, 1, 1, 0, 0, 0))
                .setId("jwt-id-1")
                .signWith(key)
                .compact();
        System.out.println(jws);
        // 校验 JWT
        Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(key).build()
                .parseClaimsJws(jws);
        Assert.assertEquals(issuer, claims.getBody().getIssuer());
        Assert.assertEquals(subject, claims.getBody().getSubject());
        // 其它校验略 ...
    }

    private Date date(int year, int month, int day, int hour, int minute, int second) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }
}

如果验签失败则会抛出 SignatureException(继承自 JwtException)。

相关文章

网友评论

    本文标题:JJWT

    本文链接:https://www.haomeiwen.com/subject/mvghvhtx.html