Java jwt使用公钥字符串验证解析token锁方法详解

下面是详细讲解“Java jwt使用公钥字符串验证解析token锁方法详解”的完整攻略。

一、什么是JWT

JWT是一种开放的标准(RFC 7519),定义了一种简洁的、自包含的方式用于在各方之间传递信息。该信息可以被验证和信任,因为它是经过数字签名的。JWT可以使用对称加密和非对称加密两种方式进行签名,其中非对称加密使用公钥和私钥进行加密和解密。

JWT包含三个部分:头部、载荷和签名,如下所示:

// 头部
{
  "alg": "HS256",
  "typ": "JWT"
}

// 载荷
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

// 签名
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

其中,头部用于描述JWT的元数据信息,如签名算法(alg)和令牌类型(typ)等。载荷包含实际的用户数据,如用户ID、用户名、过期时间等。签名则用于保证JWT的完整性和真实性,通过对头部、载荷和密钥进行签名,得到签名数据,可以用于校验JWT是否被篡改。

二、使用公钥字符串验证解析JWT

对于使用公钥字符串验证解析JWT的场景,我们需要在服务器上设置一组公钥和私钥,使用私钥对JWT进行签名,然后将JWT和公钥字符串返回给客户端。

客户端收到JWT后,在需要验证和解析JWT的地方,可以将公钥字符串转换成公钥,使用公钥对JWT进行验证和解析。

下面是一些基本的示例代码。

1. 生成JWT

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {

    private static final String ALGORITHM = "RSA";
    private static final int KEY_SIZE = 2048;
    private static final String PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
            "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDR4d/SLGU8W/cO\n" +
            "kVXIGPmL+UDzpzB9BFq+vP1dUxX+l5G0kvBdzz19oIZlp1Vsmn8c/g/ap7hTfX0Z\n" +
            //省略私钥部分
            "-----END PRIVATE KEY-----";
    private static final String PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0eHf0ixlPFv3DpFVyBj5\n" +
            "i/lA86cwfQRavrz9XVMV/peRtJLwXc89faCGZadVbJp/HP4P2qe4U319GQ6N6Zg5\n" +
            //省略公钥部分
            "-----END PUBLIC KEY-----";

    public static String createToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("sub", userId);
        claims.put("iat", Date.from(Instant.now()));
        claims.put("exp", Date.from(Instant.now().plus(1, ChronoUnit.DAYS)));
        KeyPair keyPair = generateKeyPair();
        String privateKeyString = getPrivateKeyString(keyPair);
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.RS256, keyPair.getPrivate())
                .compact();
    }

    private static KeyPair generateKeyPair() {
        KeyPairGenerator keyPairGenerator;
        try {
            keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
            keyPairGenerator.initialize(KEY_SIZE);
            return keyPairGenerator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static String getPrivateKeyString(KeyPair keyPair) {
        return "-----BEGIN PRIVATE KEY-----\n" +
                Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()) +
                "\n-----END PRIVATE KEY-----";
    }

}

此处我们使用RSA算法生成了一对公钥和私钥,并使用私钥对JWT进行签名并生成一个token。其中,私钥和公钥的字符格式是PEM格式的,需要进行解析和转换。

2. 验证和解析JWT

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class JwtUtils {

    // ...

    public static boolean verifyToken(String token) {
        try {
            PublicKey publicKey = getPublicKey();
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                    .setSigningKey(publicKey)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static Claims parseToken(String token) {
        PublicKey publicKey = getPublicKey();
        return Jwts.parserBuilder()
                .setSigningKey(publicKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    private static PublicKey getPublicKey() throws Exception {
        String publicKeyString = PUBLIC_KEY
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s","");
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

}

此处我们提供了两个方法,一个是验证token是否有效,一个是解析token中的数据(也就是头部和载荷)。在两个方法中,都使用了公钥对JWT进行验证和解析。

三、示例说明

下面是两个示例说明,分别演示了如何生成JWT和验证JWT的过程。

示例一:生成JWT

public static void main(String[] args) {
    String token = JwtUtils.createToken("123456");
    System.out.println(token);
}

运行结果:

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMjM0NTYiLCJpYXQiOjE2MjczNzc5MDcsImV4cCI6MTYyNzQ2NDA5N30.XB6WvHoltDH-5jwSBfLqM4-hnltwIz2LaklZVBZcDwzACVKKyw-aU2XxwkVGllCgjzDtl8JGtO0cc_Kh0xo3WMoovqW1uwYGW-p6pN1n8mU8tgyn2ob1nZyDK0VQU0_CXjHPScjRljwoeZoY1b24-ctKzZiS9rwver_3BIQf1-nCJ9g3trNvUfkc9vZeZKakHSMtr9v6JizlOp2R0-kwmM3whiiIH_QjAbYcqOyU_Vbgi7Q4y91umx4DXZS9O9vDuQ15rvvPvVOXdbEBhep83mRrvvFIwzmYLnEp5a5cyQKw6R7fWYBHHbDOhK3OqDKtEYDHb3pNtf7-Vw

生成的jwt包含了头部、载荷和签名信息,其中载荷中包含了sub、iat和exp等字段信息。这里我们使用了PEM格式的字符串描述了私钥和公钥,通过使用私钥对JWT进行签名和验证,提高了数据的安全性。

示例二:解析JWT

public static void main(String[] args) {
    String token = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMjM0NTYiLCJpYXQiOjE2MjczNzc5MDcsImV4cCI6MTYyNzQ2NDA5N30.XB6WvHoltDH-5jwSBfLqM4-hnltwIz2LaklZVBZcDwzACVKKyw-aU2XxwkVGllCgjzDtl8JGtO0cc_Kh0xo3WMoovqW1uwYGW-p6pN1n8mU8tgyn2ob1nZyDK0VQU0_CXjHPScjRljwoeZoY1b24-ctKzZiS9rwver_3BIQf1-nCJ9g3trNvUfkc9vZeZKakHSMtr9v6JizlOp2R0-kwmM3whiiIH_QjAbYcqOyU_Vbgi7Q4y91umx4DXZS9O9vDuQ15rvvPvVOXdbEBhep83mRrvvFIwzmYLnEp5a5cyQKw6R7fWYBHHbDOhK3OqDKtEYDHb3pNtf7-Vw";
    Claims claims = JwtUtils.parseToken(token);
    System.out.println(claims);
}

运行结果:

{sub=123456, iat=1627377907, exp=1627464097}

解析JWT后,我们得到了payload中携带的用户数据,包括sub、iat和exp字段,分别代表用户ID、JWT的签发时间和过期时间。这些数据可以根据业务需要进行进一步的处理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java jwt使用公钥字符串验证解析token锁方法详解 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • springboot框架阿里开源低代码工具LowCodeEngine

    下面给你详细讲解“springboot框架阿里开源低代码工具LowCodeEngine”的完整攻略。 介绍 LowCodeEngine 是一个基于SpringBoot框架的阿里开源低代码工具,它帮助开发者快速生成和组装 REST 接口,可以通过简单的配置文件来实现,也支持自定义。 安装步骤 下载LowCodeEngine源码包 使用Maven进行编译打包 部…

    Java 2023年5月19日
    00
  • 如何通过Java监听MySQL数据的变化

    如何通过Java监听MySQL数据的变化? 为了监听MySQL数据的变化,我们可以借助MySQL提供的binlog机制和Java的开源库Canal,来轻松实现对MySQL数据的监听与解析。Canal是阿里巴巴开源的基于binlog的增量订阅&消费组件,用于数据的异构复制和逻辑解析,在大型分布式系统下广泛应用于数据信息同步。 Canal基于阿里中间件团…

    Java 2023年5月20日
    00
  • Java中的动态和静态编译实例详解

    关于 “Java中的动态和静态编译实例详解” 的完整攻略,我们需要分别从动态编译和静态编译两个方面进行讲解。 动态编译 什么是动态编译 动态编译是指在程序运行的过程中,动态将源代码编译成字节码,并加载进JVM中执行。相对于静态编译,它需要额外的时间和资源,但是具有更高的灵活性和动态性。 实例1:Java代码实时编译 我们来看一个简单的Java代码实时编译实例…

    Java 2023年5月19日
    00
  • SpringBoot实现统一封装返回前端结果集的示例代码

    下面我来详细讲解如何实现SpringBoot的统一封装返回前端结果集的示例代码的完整攻略。 1. 为什么需要统一封装返回结果集 在我们使用SpringBoot开发Web应用时,通常经常会用到Controller来处理请求。Controller的主要作用是接收请求,处理业务逻辑,然后将结果返回给前端。通常情况下,我们在Controller方法中使用如下方式处理…

    Java 2023年5月26日
    00
  • springboot 整合邮件发送功能

    整合邮件发送功能是 Spring Boot 中常见的应用场景之一。下面是整合邮件发送功能的完整攻略: 步骤一:添加邮件依赖 在 pom.xml 文件中添加以下依赖,在这个依赖中包含了spring-boot-starter-mail的所有依赖。 <dependency> <groupId>org.springframework.boot…

    Java 2023年6月15日
    00
  • 一文搞懂JSON(JavaScript Object Notation)

    让我来为你详细讲解“一文搞懂JSON(JavaScript Object Notation)”的攻略。 概述 JSON是一种轻量级的数据交换格式,由JavaScript语言创建。它基于JavaScript的对象表示法的部分语法,但是与之不同的是,JSON可以由许多编程语言而不仅仅是JavaScript进行解析和生成。JSON格式的值可以是字符串、数值、布尔值…

    Java 2023年5月26日
    00
  • Java8优雅的字符串拼接工具类StringJoiner实例代码

    下面是关于“Java8优雅的字符串拼接工具类StringJoiner实例代码”的完整攻略。 什么是StringJoiner StringJoiner是Java 8中提供的一个字符串拼接工具类。它可以将多个字符串按照指定的分隔符连接起来,并可以指定前缀和后缀,从而生成一个完整的字符串。 StringJoiner的构造方法 public StringJoiner…

    Java 2023年5月26日
    00
  • Java编程Retry重试机制实例详解

    Java编程Retry重试机制实例详解 在实际工作中,我们经常会遇到一些不稳定的网络或服务,如果我们在请求时遇到了异常,通常需要进行重试。这时,Retry重试机制能够有效保证我们的请求能够成功返回。这篇文章就来详细讲解Java编程Retry重试机制的实例。 Retry重试机制是什么 Retry重试机制是指我们在请求某个服务时,如果第一次请求失败了,我们可以再…

    Java 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部