公私钥非对称加密 生成和验证JSON Web Token (JWT)

news2024/12/24 2:20:54

前言

这是我在这个网站整理的笔记,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱

公私钥非对称加密 生成和验证JSON Web Token

    • 什么是JSON Web Token (JWT)
    • Java程序中生成和验证JWT
    • 代码解析

什么是JSON Web Token (JWT)

JSON Web Token (JWT) 是一种轻量级的身份验证和授权机制,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。其中头部和载荷都是Base64编码的JSON对象,签名是对头部、载荷和秘钥进行加密生成的。

JWT的优点在于它是一种无状态的身份验证机制,因此可以在分布式系统中广泛使用。JWT通常作为API的身份验证机制,客户端在请求中携带JWT token,服务端通过验证JWT token来确定请求的合法性。

使用JWT作为API的身份验证机制可以避免服务器保存用户登录状态,从而提高系统的可扩展性和安全性。在实际开发中,可以根据具体需求来选择不同的加密算法和秘钥长度。

Java程序中生成和验证JWT

以下是一个Java程序,用于生成和验证JSON Web Token (JWT)。该程序使用了RSA非对称加密算法生成公私钥对,并使用私钥构建JWT token,设置了主题、签发时间、过期时间和一个自定义声明。最后,使用公钥验证JWT token,并从中获取主题信息和自定义声明。

package com.ugdsec.common.auth.common.utils;

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

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

public class JwtExample {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {

        // 生成RSA公私钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());

        // 将公钥字符串转换为公钥对象
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);

        // 将私钥字符串转换为私钥对象
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        privateKey = KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec);

        // 构建JWT token
        String jwtToken = Jwts.builder()
            .setSubject("user")
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000))
            .signWith(SignatureAlgorithm.RS256, privateKey)
            .claim("test","sdfs")
            .compact();
        System.out.println(jwtToken);

        // 验证JWT token
        Jws<Claims> jws = Jwts.parser()
            .setSigningKey(publicKey)
            .parseClaimsJws(jwtToken);

        // 获取JWT token中的主题信息和自定义声明
        String subject = jws.getBody().getSubject();
        String test = (String) jws.getBody().get("test");
        System.out.println("Subject: " + subject);
        System.out.println("Test: " + test);
    }
}

输出结果:

image-20230918141434440

代码解析

程序中使用了io.jsonwebtoken包提供的类和方法来生成和验证JWT token。具体分析如下:

  1. 导入所需的包
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
  1. 生成RSA公私钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());

使用KeyPairGenerator类生成2048位的RSA公私钥对,将公私钥分别存储在publicKeyprivateKey变量中,并将它们对应的字符串分别存储在publicKeyStringprivateKeyString变量中。

  1. 将公私钥字符串转换为公私钥对象
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);

byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
privateKey = KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec);

将公私钥对应的字符串转换成公私钥对象,以便后续使用。

  1. 构建JWT token
String jwtToken = Jwts.builder()
    .setSubject("user")
    .setIssuedAt(new Date())
    .setExpiration(new Date(System.currentTimeMillis() + 3600000))
    .signWith(SignatureAlgorithm.RS256, privateKey)
    .claim("test","sdfs")
    .compact();
System.out.println(jwtToken);

使用Jwts.builder()方法构建JWT token,设置了主题、签发时间、过期时间和一个自定义声明,并使用私钥进行签名。

  1. 验证JWT token
Jws<Claims> jws = Jwts.parser()
    .setSigningKey(publicKey)
    .parseClaimsJws(jwtToken);

使用公钥验证JWT token,并将解析后的结果存储在jws变量中。

  1. 获取JWT token中的主题信息和自定义声明
String subject = jws.getBody().getSubject();
String test = (String) jws.getBody().get("test");
System.out.println("Subject: " + subject);
System.out.println("Test: " + test);

作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】泛型算法(二)泛型指针Iterator(迭代器)

迭代器iterator定义 迭代器是一种检查容器内元素并遍历元素的数据类型&#xff1b;迭代器提供一个对容器对象或者string对象的访问方法&#xff0c;并定义了容器范围&#xff1b;迭代器的使用可以提高编程的效率。 其定义应该提供&#xff1a; 迭代对象&#xff08;某个容器&a…

拆贡献算总和(抓住双射)+竞赛图与连通分量相关计数:arc163_d

https://atcoder.jp/contests/arc163/tasks/arc163_d 首先竞赛图有个性质&#xff1a; 然后有了这个性质&#xff0c;我们就可以考虑计数题的经典套路&#xff0c;拆贡献算总和。 考虑假如我们成功划分成两个集合 A , B A,B A,B&#xff0c;其中一个可以为空&#xff08;我们…

Qt --- Day02

实现效果&#xff1a; 点击登录&#xff0c;检验用户密码是否正确&#xff0c;正确则弹出消息框&#xff0c;点击ok转到另一个页面 不正确跳出错误消息框&#xff0c;默认选线为Cancel&#xff0c;点击Yes继续登录 点击Cancel跳出问题消息框&#xff0c;默认选项No&#xff0c…

netty之pipeline

Netty抽象出流水线(pipeline)这一层数据结构进行处理或拦截channel相关事件。 事件分为入站事件(inBound event)和出站事件(outBound event)的ChannelHandlers列表。ChannelPipeline使用先进的Intercepting Filter模式&#xff0c;使用户可以完全控制如何处理事件以及管道中的…

全流程GMS地下水数值模拟及溶质(包含反应性溶质)运移模拟技术教程

详情点击公众号链接&#xff1a;全流程GMS地下水数值模拟及溶质&#xff08;包含反应性溶质&#xff09;运移模拟技术教程 前言 GMS三维地质结构建模 GMS地下水流数值模拟 GMS溶质运移数值模拟与反应性溶质运移模 详情 1.GMS的建模数据的收集、数据预处理以及格式等&#xff…

2023/9/18 -- C++/QT

作业 完善登录框 点击登录按钮后&#xff0c;判断账号&#xff08;admin&#xff09;和密码&#xff08;123456&#xff09;是否一致&#xff0c;如果匹配失败&#xff0c;则弹出错误对话框&#xff0c;文本内容“账号密码不匹配&#xff0c;是否重新登录”&#xff0c;给定两…

《Linux运维总结:Centos7.6之OpenSSH7.4升级版本至9.4》

一、环境信息 操作系统&#xff1a;Centos7.6.1810 OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 如下图所示&#xff1a; 注意&#xff1a;升级后由于加密算法的区别&#xff0c;低版本的SSH工具可能无法连接&#xff0c;建议改用Xshell7或SecureCRT9.0以上版本。 二、注意事项 1、检…

第九章 关系查询处理和查询优化

第九章 关系查询处理和查询优化 9.1 关系数据库系统的查询处理 9.1.1 查询处理步骤 查询分析 对查询语句进行扫描、词法分析和语法分析&#xff0c; 词法分析&#xff1a;从查询语句中识别出正确的语言符号。语法分析&#xff1a;进行语法检查。 查询检查 合法性检查视图转换…

【java】【SpringBoot】【二】运维实用篇 SpringBoot工程

目录 一、打包与运行 1、程序打包与运行&#xff08;Window版&#xff09; 1.1 打包 1.2 运行 1.3 打包插件 1.4 总结 1.6 命令行启动常见问题及解决方案 2、程序运行&#xff08;Linux版&#xff09; 二、配置高级 1、临时属性设置 2、配置文件分类 3、自定义配置…

Spring Boot + Vue3前后端分离实战wiki知识库系统十三--单点登录开发二

接着https://www.cnblogs.com/webor2006/p/17608839.html继续往下。 登录功能开发&#xff1a; 接下来则来开发用户的登录功能&#xff0c;先准备后端的接口。 后端增加登录接口&#xff1a; 1、UserLoginReq&#xff1a; 先来准备用户登录的请求实体&#xff1a; package com…

07JVM_内存模型和CAS与原子类

一、内存模型 1.java内存模型 Java内存结构是JMM&#xff08;Java Memory Model&#xff09;的意思。JMM定义了一套在多线程读写共享数据&#xff08;成员变量&#xff0c;数组&#xff09;时&#xff0c;对数据的原子性&#xff0c;见性&#xff0c;有序性的规则和保障。 1…

浅谈电力电容器技术的发展及选型

安科瑞 华楠 摘要&#xff1a;介绍了我国电力电容器产品制造技术的发展现状。在与国外电力电容器产品先进水平对比的基础上,讨论了我国电力电容器产品的差距和某些对策,并对我国电力电容器技术发展趋势提出了一些看法。 关键词&#xff1a;电力电容器;制造技术;技术发展 0 引…

每日一题~最大二叉树

题目链接&#xff1a;654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数…

Logstash介绍

Logstash介绍 Logstash是一个开源数据收集引擎&#xff0c;具有实时管道功能。Logstash可以动态地将来自不同数据源的数据统一起来&#xff0c;并将数据标准化到你所选择的目的地。 集中、转换和存储你的数据 Logstash是一个开源的服务器端数据处理管道&#xff0c;可以同时从多…

采集分析仪设计原理图:437-带触摸显示的10路5Msps@18bit采集分析仪

带触摸显示的10路5Msps18bit采集分析仪 一、产品概述 本产品提供了多种传感器接入接口&#xff0c;支持多种类型传感器实时采集、处理、显示等功能。主处理器采用XC7Z100-FFG900芯片&#xff0c;具有444K逻辑单元和双核ARM Cortex-A9 MPCore处理器。PL部分得可编程逻辑可…

docker系列-报错以及解决指南

1. windows运行docker报错Windows Hypervisor is not presentDocker Desktop is unable to detect a Hypervisor.Hardware assisted virtualization and data execution protection must be enabled in the BIOS. Docker Desktop - Windows Hypervisor is not presentDocker D…

async和await的用法

定义 async的定义 在mdn中,async的定义为: async function 关键字可用于定义表达式中的异步函数。 其实很简单,就是async关键字后面定义的函数会被转化为一个异步的函数 如下所示: function fn1(){return 同步}async function asyncFn(){return 异步}console.log(fn1())con…

Dubbo3应用开发——架构的演变过程

Dubbo3应用开发——架构的演变过程 什么是Dubbo 早期Dubbo的定位&#xff1b; 基于Java的高性能&#xff0c;轻量级的RPC框架&#xff1b;SOA【Service-Oriented Architecture ⾯向服务的架构】 RPC服务治理&#xff1b; 2018年阿⾥巴巴把这个框架捐献给了 Apache 基⾦会&am…

深入理解Java单例模式和优化多线程任务处理

目录 饿汉模式懒汉模式单线程版多线程版双重检查锁定 阻塞队列 单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例&#xff0c;并提供一个全局访问点。 饿汉模式 类加载的同时&#xff0c;创建实例。 class Singleton {private static final Singlet…