基于JJWT理解JWT,JWS,JWE

news2024/9/22 18:21:32

JWT , 全写JSON Web Token, 是开放的行业标准RFC7591,用来实现端到端安全验证.
从开发者理解的角度来说:

  • JWT 是一个定义传递信息的标准
  • JWT 的Token是一个Base64编码的字符串, 类似
eyJhbGciOiJIUzI1NyJ9.eyJzdWIiOiJvc2NhciJ9.p1no61S/XIQ0QNEhzB8e0eI9Q39jIGgkDxUjYipKnzw=

这个字符串里面包含2个点号(.),可以分成3段, 分别表示头部,负载和签名。

关于JWT的更多介绍,可以参考:
JWT介绍以及java-jwt的使用

JWT Token是如何产生的

  1. 最简单的JWT由两部分组成: header(头部) 和 payload(负载)
    关于JWT的基本介绍, 可以参考:
    JWT介绍以及java-jwt的使用

比如头部是:

{
  "alg": "none"
}

负载是:

Hello, JWT
  1. 移除不必要的空格
		String header = "{\"alg\":\"none\"}";
		String payload= "Hello, JWT";
  1. 获取UTF-8的字节后,使用Base64进行编码
		String encodedHeader = Base64.getEncoder().encodeToString(header.getBytes());
		String encodedPayload = Base64.getEncoder().encodeToString(payload.getBytes());

4.将编码后的字符使用点号(.) 连接起来

String compact= encodedHeader + "." + encodedPayload + ".";

连接后的Token如下:

eyJhbGciOiJub25lIn0=.SGVsbG/vvIwgSldU.

从这里可以看出, JWT其实并不神秘, 只是对字符串进行了Base64编码, 所以通过解码或是一些在线的Base64解码的工具就可以直接得到结果了,比如 https://base64.us/
在这里插入图片描述

因为没有进行数字签名,上面的Token是不安全和未受保护的, 不能保证没有第三方对这个内容进行修改,所以为了提升安全,就需要添加数字签名。

JWS ,signedJWT -加密签名的JWT

上面的示例payload是一个字符串, 但实际使用时,payload更多是JSON 格式的数据, 对JWT进行数字签名后的Token 就称为JWS了。

还是从简单的示例来看:

  1. 头部
{
  "alg": "HS256"
}

使用HS256算法进行数字签名
2. 负载

{
"sub":"oscar"
}
  1. 去除空格的内容
		String header = "{\"alg\":\"HS257\"}";
		String payload=  "{\"sub\":\"oscar\"}";
  1. 获取字节数组和使用Base64编码,并且使用点号连接
		String encodedHeader = Base64.getEncoder().encodeToString(header.getBytes());
		String encodedPayload = Base64.getEncoder().encodeToString(payload.getBytes());
		String concatenated = encodedHeader + '.' + encodedPayload;
  1. 使用足够安全的摘要加密算法(比如使用HMAC-SHA-256), 获取加密后的摘要,也就是数字签名。最后将头部、负载和签名组合起来就是一个完整的Token 了。
		String header = "{\"alg\":\"HS257\"}";
		String payload=  "{\"sub\":\"oscar\"}";
		Key secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
		String encodedHeader = Base64.getEncoder().encodeToString(header.getBytes());
		String encodedPayload = Base64.getEncoder().encodeToString(payload.getBytes());
		String concatenated = encodedHeader + '.' + encodedPayload;
		
		Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        sha256_HMAC.init(secretKey);
        byte[] signature = sha256_HMAC.doFinal(concatenated.getBytes("utf-8"));//使用加密算法产生签名
        String compact = concatenated + '.' + Base64.getEncoder().encodeToString( signature ); //将签名和头,载荷连接起来
        System.out.println(compact);

由此产生的Token如下:

eyJhbGciOiJIUzI1NyJ9.eyJzdWIiOiJvc2NhciJ9.HjomJsGXx3vO/x16euJo7kFsBFJaOEdyoj5Czbt3XE4=

JWE,  encrypted JWT

JWE就是对数字签名的Token进行加密,加密之后使用Base64解码之后是无法直接获取Token的内容的, 加密的方式可以是对称加密, 可以是非对称加密。JJWT也提供了一些加密的快速方法, 但是在不同的版本中支持有差异, 这里使用Java 本身的DES对称加密进行演示。
示例代码如下:

	
	@Test
	public void jwe() throws Exception {
		String header = "{\"alg\":\"HS257\"}";
		String payload = "{\"sub\":\"oscar\"}";
		Key secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
		String encodedHeader = Base64.getEncoder().encodeToString(header.getBytes());
		String encodedPayload = Base64.getEncoder().encodeToString(payload.getBytes());
		String concatenated = encodedHeader + '.' + encodedPayload;

		Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
		sha256_HMAC.init(secretKey);
		byte[] signature = sha256_HMAC.doFinal(concatenated.getBytes("utf-8"));
		String compact = concatenated + '.' + Base64.getEncoder().encodeToString(signature);
		
		//使用DES算法对称加密
		String strKey = "this is my password";
		DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey key = keyFactory.generateSecret(desKeySpec);

		Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, key);

		byte[] encryptedBytes = cipher.doFinal(compact.getBytes(StandardCharsets.UTF_8));
		String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
		System.out.println(encryptedText);
		
	}

加密之后的Token使用Base64解码后得到的内容如下:
在这里插入图片描述

要得到正确的内容, 需要使用密钥进行解密之后, 再进行Base64解码。

关于Java对称加密与解密, 可以参考:
Java实现对称加密(DES,AES)快速入门示例

名词解释

  • JWT, JSON Web Token。 JSON格式的Web令牌
  • JWS: signed JWT,签名的JWT
  • JWE: encrypted JWT,签名且加密的JWT(对负载也加密)

三者的关系如下:
在这里插入图片描述

完整示例代码

  • https://github.com/osxm/java-ency/blob/master/src/main/java/com/osxm/je/topic/security/JjwtDemo.java


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

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

相关文章

Vue下载及配置(Vue文件和路由文件)

目录 Vue文件2.7.14版本: Vue路由: 结束: Vue文件2.7.14版本: Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容ECMAScript5的浏览器 Vue文件下载地址:安…

openLayers实战(九):正多边形的绘制

最近在绘制各种图形,越来越乱,看了很多文章,启发了从最最基础的图形开始学习扩展。 遇到什么样的问题? import ol from "ol"; import { Draw } from "ol/interaction"; import { Vector as VectorSource } f…

帆软报表开发-快速入门

帆软学习:帆软学院-培养企业亟需的数据人才 第一章 初识FineReport 1、初识FineReport 1.1、FineReport 是什么? FineReport 是一款简单、高效、智能的报表工具,用以快速搭建的企业级Web报表平台。 FineReport 报表主要功能介绍 ① 主要…

Ubuntu 20.04使用Livox mid 360 测试 FAST_LIO

前言 Livox mid360需要使用Livox-SDK2,而非Livox-SDK,以及对应的livox_ros_driver2 。并需要修改FAST_LIO中部分代码。 1. 安装Livox-SDK2 参考官方教程。 1.1. 安装CMake sudo apt install cmake1.2. 安装编译Livox-SDK2 git clone https://github…

BDA初级分析——可视化图形

一、时间趋势 时间趋势要如何呈现? Excel函数补充 YEAR:提取日期中的年份MONTH:提取日期中的月份DAY:提取日期中的天HOUR:提取时间中的小时 TEXT:将数值转换为按指定数字格式表示的函数 写法&#xff1…

关于lattice planner

使用编程创建驾驶场景。 1.使用Driving scenario Designer 交互方式创建驾驶场景 2.导出matalb function 3.修正这个函数,创建原始场景的变体。 4.调用这个函数,生成drivingScenario object。 5.在simulink中仿真,导入这个objcet &…

无涯教程-PHP - File 函数

文件系统功能用于访问和操纵文件系统&#xff0c;PHP为您提供了操纵文件的所有功能。 运行时配置 这些功能的行为受php.ini中的设置影响。 NameDefaultChangeableChangelogallow_url_fopen"1"PHP_INI_ALLPHP_INI_ALL in PHP < 4.3.4. PHP_INI_SYSTEM in PHP &l…

网络编程(IO模型)

一、阻塞IO 1.最常用&#xff0c;最简单&#xff0c;效率最低的。 2.创建套接字文件描述符后&#xff0c;默认处于阻塞IO模式; 3.read, write, recv, send, recvfrom ,sendto&#xff0c;accept 二. 非阻塞IO 1.防止进程阻塞在IO函数上&#xff0c;但是如果想要获取到有效…

WebRTC音视频通话-iOS端调用ossrs直播拉流

WebRTC音视频通话-iOS端调用ossrs直播拉流 之前实现iOS端调用ossrs服务&#xff0c;文中提到了推流。没有写拉流流程&#xff0c;所以会用到文中的WebRTCClient。请详细查看&#xff1a;https://blog.csdn.net/gloryFlow/article/details/132257196 一、iOS播放端拉流效果 二…

A*算法图文详解

基本概念 A*算法最早于1964年在IEEE Transactions on Systems Science and Cybernetics中的论文《A Formal Basis for the Heuristic Determination of Minimum Cost Paths》中首次提出。其属于一种经典的启发式搜索方法&#xff0c;所谓启发式搜索&#xff0c;就在于当前搜索…

【校招VIP】测试计划之H5测试

考点介绍&#xff1a; H5即HTML的第5个版本&#xff0c;是一种高级的网页技术&#xff0c;可以理解为一个网页。使用原生制作APP&#xff0c;即在基于目前的智能手机的操作系统&#xff08;Android、iOS、Windows phone&#xff09;的基础上&#xff0c;使用相应平台支持的开发…

五金实体店:如何快速开发做出自己的小程序商城?

现如今&#xff0c;小程序已经成为了各行各业的发展趋势&#xff0c;对于五金实体店而言&#xff0c;开发一个自己的小程序商城能够帮助实现线上线下融合&#xff0c;扩大销售渠道&#xff0c;提升品牌影响力。下面就让我们来了解如何快速开发一个小程序商城吧。 首先&#xff…

[赛博昆仑] 腾讯QQ_PC端,逻辑漏洞导致RCE漏洞

简介 !! 内容仅供学习,请不要进行非法网络活动,网络不是法外之地!! 赛博昆仑是国内一家较为知名的网络安全公司&#xff0c;该公司今日报告称 Windows 版腾讯 QQ 桌面客户端出现高危安全漏洞&#xff0c;据称“黑客利用难度极低、危害较大”&#xff0c;腾讯刚刚已经紧急发布…

STP知识总结

目录 生成树协议 导致问题 生成树 存在算法 1、802.1D 接口状态 收敛时间 结构变化 802.1D 缺点 2、PVST cisco私有 3、PVST 缺点 4、快速生成树 快速原理 边缘接口 5、MSTP/MST/802.1S 生成树协议 生成树协议是一种工作在OSI网络模型中第二层(数据链路层…

TCP特点UDP编程

目录 1、tcp协议和udp协议 2、多线程并发和多进程并发&#xff1a; &#xff08;1&#xff09;多进程并发服务端 &#xff08;2&#xff09;多进程并发客户端&#xff1a; 3、tcp: 4、粘包 5、UDP协议编程流程 (1)服务器端&#xff1a; (2)客户端&#xff1a; 6、tcp状…

JavaEE初阶:Java线程的状态

目录 获取当前线程引用 休眠当前线程 线程的状态 1.NEW 2.TERMINATED 3.RUNNABLE 4.WAITING 5.TIMED_WAITING 6.BLOCKED 多线程的意义 单线程 多线程 获取当前线程引用 public static Thread currentThread(); 这个方法返回当前线程的引用。但是我…

WSL2 Ubuntu20.04 配置 CUDA

前言 本文主要讲解如何在 Widnows 11 环境下的 WSL2&#xff08;Ubuntu20.04&#xff09;配置 CUDA 来启用 GPU 加速&#xff08;本文默认您已经在 Windows 上安装完成 Nvidia CUDA&#xff09; 配置流程 检查驱动 打开 GeForce Experience 检查驱动程序的情况&#xff0c;…

基于 BlockQueue(阻塞队列) 的 生产者消费者模型

文章目录 阻塞队列&#xff08;BlockQueue&#xff09;介绍生产者消费者模型 介绍代码实现lockGuard.hpp&#xff08;&#xff09;Task.hpp&#xff08;任务类&#xff09;BlockQueue.hpp&#xff08;阻塞队列&#xff09;conProd.cc&#xff08;生产者消费者模型 主进程&#…

从来不懂K8s的人10分钟内将应用跑在了K8s中

大家可能都听说过 K8s 或者 docker &#xff0c;可能有容器编排的概念&#xff0c;知道这会提高运维效率&#xff0c;但是由于上手难度高迟迟没有学习它。 今天我以自己的实际经历教大家将自己的应用在10分钟内部署到k8s中&#xff0c;你不需要懂任何的 docker 命令和 k8s 命令…