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

yizhihongxing

下面是详细讲解“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日

相关文章

  • Java 如何实现时间控制

    Java 中实现时间控制的方式有很多种,其中比较常用的有以下几种: 方式一:使用 Timer 和 TimerTask 类 Java 通过 Timer 和 TimerTask 类可以实现简单的时间控制功能。Timer 是一个定时器类,可用于在指定时间间隔内重复执行某个操作。TimerTask 则是一个抽象类,用于在指定时间执行某个操作。通过这两个类的组合使用,…

    Java 2023年5月20日
    00
  • SpringBoot 配合 SpringSecurity 实现自动登录功能的代码

    下面我就来详细讲解一下 “SpringBoot 配合 SpringSecurity 实现自动登录功能的代码”的完整攻略。 什么是自动登录功能 自动登录(Remember Me)是指用户可以选择保存登录状态,保留一定时间不失效。这样用户可以在再次打开网站时,不需要重新输入用户名密码,而是直接使用之前的登录信息登录进去。 操作步骤 1. 导入相关依赖 在 pom…

    Java 2023年5月20日
    00
  • java中全排列的生成算法汇总

    Java中全排列的生成算法汇总 一、什么是全排列 全排列,是指将一组数按一定顺序进行排列,称为这组数的全排列。 如有三个数a、b、c,则它们的全排列有:a、b、c、ab、ac、ba、bc、ca、cb、abc、acb、bac、bca、cab、cba 共6个。 二、生成全排列的算法 在Java中,生成全排列的算法有以下几种: 1.递归算法 这种算法实现简单,思路…

    Java 2023年5月19日
    00
  • Java使用反射操作数组示例

    Java反射是在程序运行时可以动态获取类的信息并操作类的属性、方法和构造器。在Java中,数组是一种特殊类型的对象,因此也可以使用反射操作数组。本文将讲述如何使用Java反射操作数组,包括获取数组信息、读取/修改数组元素、创建新数组等。 获取数组信息 要对数组进行反射操作,首先需要获取数组对象的所有信息,常用的方法有以下两种: // 获取数组类型 Strin…

    Java 2023年5月26日
    00
  • 详解SpringMVC中的四种跳转方式、视图解析器问题

    以下是关于“详解SpringMVC中的四种跳转方式、视图解析器问题”的完整攻略,其中包含两个示例。 SpringMVC中的四种跳转方式 SpringMVC中有四种跳转方式,分别是: forward redirect internalRedirect sendRedirect 1. forward forward是一种服务器内部跳转方式,它将请求转发给另一个控…

    Java 2023年5月16日
    00
  • Struts2实现文件下载功能代码分享(文件名中文转码)

    下面是详细的“Struts2实现文件下载功能代码分享(文件名中文转码)”攻略: 1. 背景介绍 Struts2是一个优秀的MVC框架,而文件下载是很多Web项目中常见的需求。本文将介绍如何在Struts2中实现文件下载功能,并且解决中文文件名乱码的问题。 2. 实现步骤 2.1 编写Action 首先,我们需要创建一个Action类,用于处理文件下载请求。该…

    Java 2023年5月20日
    00
  • JAVA深入探究之Method的Invoke方法

    JAVA深入探究之Method的Invoke方法 在Java中,使用Method类可以描述一个方法。Method类提供了invoke()方法,可以反射调用一个方法。本文将讲解Method的invoke方法的使用方法及示例。 什么是Method的Invoke方法 Method的Invoke方法是Java中反射调用方法的主要方法。它可以调用任意一个对象的任意一个…

    Java 2023年5月26日
    00
  • 详解AngularJs与SpringMVC简单结合使用

    详解AngularJs与SpringMVC简单结合使用攻略 1. 基本介绍 AngularJS 是一个非常流行的前端框架,提供了很多便捷的功能,比如:双向数据绑定、动态页面加载、表单验证等。而 SpringMVC 是一个非常流行的 Java Web 框架,它提供了很多便捷的功能,比如:MVC 设计模式、请求映射、数据绑定等。将 AngularJS 和 Spr…

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