Java如何生成Jwt之使用Hutool实现Jwt

Java如何生成Jwt之使用Hutool实现Jwt

前置条件

项目中需要引入依赖:

xml 复制代码
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.43</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>6.1.0-M1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

1、RS256-使用Hutool生成JWT的简单示例

  • 这里使用的加密模式为:RS256
  • payload是一些自定义的参数,一般不建议太多的自定义参数,且不可存放敏感数据
  • 这个示例仅作原理讲解使用,公钥和私钥是实时生成的没有存储下来

代码如下

java 复制代码
    @Test
    public void testJwtRsa() throws Exception{

        // 1. 生成RSA密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // RSA密钥长度
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();


        // 2. 创建签名器
        JWTSigner signer = JWTSignerUtil.rs256(privateKey);

        // 3. 设置JWT的payload(载荷)自定义参数
        Map<String, Object> payload = new HashMap<>();
        payload.put("name", "John Doe");
        payload.put("admin", true);

        // 4. 设置JWT的header(头部)
        Map<String, Object> headers = new HashMap<>();
        headers.put("typ", "JWT");
        headers.put("alg", "RS256");

        // 5. 创建JWT
        String token = JWT.create()
                .addHeaders(headers)
                .addPayloads(payload)
                // 订阅者ID
                .setSubject("UID2026010100089")
                //.addPayloads(payload)
                // 设置过期时间(30分钟后)
                .setExpiresAt(DateUtil.offsetMinute(new Date(), 30))
                // 设置签发时间
                .setIssuedAt(new Date())
                // 生效时间
                .setNotBefore(new Date())
                // 设置签发者
                .setIssuer("your-app-name")
                .setJWTId(UUID.randomUUID().toString().replaceAll("-", ""))
                // 设置受众
                .setAudience("client-app")
                // 使用RS256算法签名
                .setSigner(signer)
                .sign();

        System.out.println("生成的JWT (RS256):");
        System.out.println(token);
        System.out.println();

        // 6. 验证和解析JWT
        JWT jwt = JWT.of(token);

        // 创建验证签名器
        JWTSigner verifier = JWTSignerUtil.rs256(publicKey);

        // 验证签名
        boolean verifyResult = jwt.setSigner(verifier).verify();
        System.out.println("签名验证结果: " + verifyResult);

        // 验证过期时间
        boolean validateResult = jwt.validate(0);
        System.out.println("JWT验证结果: " + validateResult);

        // 7. 获取payload数据
        System.out.println("\nPayload数据:");
        System.out.println("Subject: " + jwt.getPayload("sub"));
        System.out.println("Name: " + jwt.getPayload("name"));
        System.out.println("Admin: " + jwt.getPayload("admin"));
        System.out.println("签发者: " + jwt.getPayload("iss"));
        System.out.println("过期时间: " + jwt.getPayload("exp"));
    }

2、使用固定的公钥私钥

  • JWT签名使用公钥
  • JWT验签使用私钥
  • 因此一般私钥一定要在服务端保存好,一般需要通过加密存储,或者使用限制权限读取的方式进行保存

2.1、生成RSA的密钥对

这里我提供了基于hutool的两种方式,如下代码示例:

java 复制代码
    @Test
    public void testGenerateRsaKey() throws Exception {
        // 1、生成默认的RSA密钥对
        RSA rsa = new RSA();
        String privateKeyBase64 = rsa.getPrivateKeyBase64();
        String publicKeyBase64 = rsa.getPublicKeyBase64();
        System.out.println("privateKeyBase64:" + privateKeyBase64);
        System.out.println("publicKeyBase64:" + publicKeyBase64);
        

        // 2、指定生成的密钥长度
        KeyPair rsa1 = SecureUtil.generateKeyPair("RSA", 2048);
        System.out.println("rsa1.privateKey:" + Base64.encode(rsa1.getPrivate().getEncoded()));
        System.out.println("rsa1.publicKey:" + Base64.encode(rsa1.getPublic().getEncoded()));
    }

2.2、使用固定的公私玥生成JWT及验证JWT示例

我这里仅作示例,公钥和私钥明文展示,一般在生产环境,密钥必须加密

java 复制代码
    @Test
    public void testGenerateJwtFromRsa() throws Exception {

        String publicKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCI0CZ/FiZcpaddf+zRmRc0g6gWBINrucBRuAjlyfNOAXe8H18Xwnj/4c4duMlg4bBlOyYlQ0wo8/k7URDcLE6kRORedRDkJW1OeWsdaqzTAJ+9rkZUN5w5CZsgLvaRYY2Tl1Whai6WFgyJPguT5ojl7DSc44lBnG9cCeMK2O9QEQIDAQAB";
        String privateKeyBase64 = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIjQJn8WJlylp11/7NGZFzSDqBYEg2u5wFG4COXJ804Bd7wfXxfCeP/hzh24yWDhsGU7JiVDTCjz+TtRENwsTqRE5F51EOQlbU55ax1qrNMAn72uRlQ3nDkJmyAu9pFhjZOXVaFqLpYWDIk+C5PmiOXsNJzjiUGcb1wJ4wrY71ARAgMBAAECgYAqIZ+ZR2Ls6P6PZpOxQCnLPDgI/77Q79Tv1XK4AObyQLV0s1x/Xp4QfqMQuBUbxqShqANpOj475lX8FEzS4Loem5JeVGNpevNd3HYCVf7ylaWi7wzMm5y/y/O/dJb4o2Fk+6WODbZ9/fKIPDfOgKTyPYD8kZgufRLuvGBqATUreQJBAKCWYUQ5Dhs9xWLia+8FMjF5KnQVLbU48vlaIvb7H19cmpH7iT9B5fZwB+0xaWG4YMpSY39VcY4NJVrXBARw9ssCQQDaGadbfe31Uk5pUKsKCRbLI7n1EIEy45kp9WWIRScJzTd3bh1NMPxGrFVKdWqE+Ubr6HBO6H2drQeVAO9+yB0TAkBc31uVZyHfY1QaojQl4e1ra1XAGNd8bVkoGJcMG6PDNP033C895FCou5X5+Y+msklX+VoNtE6eBsBJzvxFzUcNAkAF6eYoy+xU14t6vY41snNkxK45H95w88zmX1oGbOGXGXJkkZ7HxglBHVEeuLpPqraqlN3etd0aFmP7PVBBHsnzAkBcZJv/Jue8PGHgfeNHS1hj4R7DRX0b3MLxyvFjloF3rjd56IuLJN9BXfiY8L+upcTsIP+B9hkstt5ge7/McJsy";

        // 加载生成密钥对
        PrivateKey privateKey = loadPrivateKey(privateKeyBase64);
        PublicKey publicKey = loadPublicKey(publicKeyBase64);

        // 2. 创建签名器
        JWTSigner signer = JWTSignerUtil.rs256(privateKey);

        // 3. 设置JWT的payload(载荷)自定义参数
        Map<String, Object> payload = new HashMap<>();
        payload.put("name", "John Doe");
        payload.put("admin", true);

        // 4. 设置JWT的header(头部)
        Map<String, Object> headers = new HashMap<>();
        headers.put("typ", "JWT");
        headers.put("alg", "RS256");

        // 5. 创建JWT
        String token = JWT.create()
                .addHeaders(headers)
                .addPayloads(payload)
                // 订阅者ID
                .setSubject("UID2026010100089")
                //.addPayloads(payload)
                // 设置过期时间(30分钟后)
                .setExpiresAt(DateUtil.offsetMinute(new Date(), 30))
                // 设置签发时间
                .setIssuedAt(new Date())
                // 生效时间
                .setNotBefore(new Date())
                // 设置签发者
                .setIssuer("your-app-name")
                .setJWTId(UUID.randomUUID().toString().replaceAll("-", ""))
                // 设置受众
                .setAudience("client-app")
                // 使用RS256算法签名
                .setSigner(signer)
                .sign();

        System.out.println("生成的JWT (RS256):");
        System.out.println(token);
        System.out.println();

        // 6. 验证和解析JWT
        JWT jwt = JWT.of(token);

        // 创建验证签名器
        JWTSigner verifier = JWTSignerUtil.rs256(publicKey);

        // 验证签名
        boolean verifyResult = jwt.setSigner(verifier).verify();
        System.out.println("签名验证结果: " + verifyResult);

        // 验证过期时间
        boolean validateResult = jwt.validate(0);
        System.out.println("JWT验证结果: " + validateResult);

        // 7. 获取payload数据
        System.out.println("\nPayload数据:");
        System.out.println("Subject: " + jwt.getPayload("sub"));
        System.out.println("Name: " + jwt.getPayload("name"));
        System.out.println("Admin: " + jwt.getPayload("admin"));
        System.out.println("签发者: " + jwt.getPayload("iss"));
        System.out.println("过期时间: " + jwt.getPayload("exp"));


    }

    /**
     * 加载RSA私钥
     * @param base64PrivateKey
     * @return
     */
    public static PrivateKey loadPrivateKey(String base64PrivateKey) {
        byte[] keyBytes = Base64.decode(base64PrivateKey);
        return KeyUtil.generateRSAPrivateKey(keyBytes);
    }

    /**
     * 加载RSA公钥
     * @param base64PublicKey
     * @return
     */
    public static PublicKey loadPublicKey(String base64PublicKey) {
        byte[] keyBytes = Base64.decode(base64PublicKey);
        return KeyUtil.generateRSAPublicKey(keyBytes);
    }
相关推荐
瑞雪兆丰年兮1 小时前
[从0开始学Java|第六天]Java方法
java·开发语言
u0109272712 小时前
模板编译期排序算法
开发语言·c++·算法
一点技术2 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
datalover2 小时前
CompletableFuture 使用示例
java·开发语言
m0_686041612 小时前
C++中的适配器模式变体
开发语言·c++·算法
清风~徐~来2 小时前
【视频点播系统】WebSocketpp 介绍及使用
开发语言
爱吃大芒果2 小时前
Flutter for OpenHarmony 实战:mango_shop 路由系统的配置与页面跳转逻辑
开发语言·javascript·flutter
学***54232 小时前
如何轻松避免网络负载过大
开发语言·网络·php
RANCE_atttackkk2 小时前
Springboot+langchain4j的RAG检索增强生成
java·开发语言·spring boot·后端·spring·ai·ai编程