jwt的了解和使用以及大致代码分析
jwt简介
以下介绍来自官网(https://jwt.io/)
SON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名**(来自官网)**。
尽管 JWT 可以加密以提供各方之间的保密性,但我们将专注于签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌则向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是签名的一方**(来自官网)**。
使用场景
-
授权:这是使用 JWT 的最常见方案。用户登录后,每个后续请求都将包含 JWT,允许用户访问使用该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且能够跨不同域轻松使用**(来自官网)**。
-
信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。由于 JWT 可以签名(例如,使用公钥/私钥对),因此您可以确定发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否未被篡改**(来自官网)**)。
jwt的组成结构
- Header
- Payload
- Signature
因此,JWT 通常如下所示。
xxxxx.yyyyy.zzzzz
Header
通常由两部分组成:令牌的类型(即 JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。
例如:
{"alg": "HS256","typ": "JWT"
}
然后,此JSON被Base64Url编码以形成JWT的第一部
Payload(有效载荷)
令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的语句。
有三种类型的声明:已注册、公共和私人声明。
已注册声明:这些是一组预定义的声明,这些声明不是必需的,但建议使用,以提供一组有用的、可互操作的声明。其中一些是:iss(发行人),exp(到期时间),sub(主题),aud(受众)等。
请注意,声明名称只有三个字符长,因为 JWT 应该是紧凑的。
公共声明:这些可以由使用 JWT 的人随意定义。但为了避免冲突,它们应该在 IANA JSON Web 令牌注册表中定义,或者定义为包含抗冲突命名空间的 URI。
专用声明:这些是创建的自定义声明,用于在同意使用它们的各方之间共享信息,既不是注册声明也不是公共声明。
示例有效负载可以是:
{"sub": "1234567890","name": "John Doe","admin": true
}
sub是预定义的声明,name,admin则是自己随便添加的一些定义
然后对有效负载进行 Base64Url 编码以形成 JSON Web 令牌的第二部分。
请注意,对于签名令牌,此信息虽然受到篡改保护,但任何人都可以读取。不要将机密信息放在 JWT 的有效负载或标头元素中,除非它已加密。
签名
要创建签名部分,您必须获取编码的标头、编码的有效负载、机密、标头中指定的算法并对其进行签名。
例如,如果要使用 HMAC SHA256 算法,将按以下方式创建签名:
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
签名用于验证消息在此过程中未被更改,并且在使用私钥签名的令牌的情况下,它还可以验证 JWT 的发件人是否是它所说的人。
把所有东西放在一起
输出是三个由点分隔的 Base64-URL 字符串,可以在 HTML 和 HTTP 环境中轻松传递,同时与基于 XML 的标准(如 SAML)相比更加紧凑。
使用java-jwt来生成和解析token
导入maven依赖
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>
这附上一段我之前写的代码
public String getToken(Users user) {String token="";// 2*24*3600 * 1000token= JWT.create().withExpiresAt(new Date(System.currentTimeMillis() + (2*24*3600*1000))).withAudience(user.getEmployeeId())// 将 login_user 保存到 token 里面.sign(Algorithm.HMAC256(DigestUtils.md5Hex(user.getEmployeePassword()+ Constants.MD5PRIVATEKEY)));// 以 password 作为 token 的密钥return token;}
这是上面引入的依赖提供的方法
首先是 JWT.create(),create方法去调用了JWTCreator的init方法
public static JWTCreator.Builder create() {return JWTCreator.init();}
然后init方法又new了一个自己的内部类,内部类给头部(headerClaims)和载荷(payloadClaims)声明了引用地址
/*** Initialize a JWTCreator instance.** @return a JWTCreator.Builder instance to configure.*/static JWTCreator.Builder init() {return new Builder();}/*** The Builder class holds the Claims that defines the JWT to be created.*/public static class Builder {private final Map<String, Object> payloadClaims;private Map<String, Object> headerClaims;Builder() {this.payloadClaims = new HashMap<>();this.headerClaims = new HashMap<>();}
紧接着withExpiresAt()和withAudience()实际上就是给载荷里预定义的声明赋值,withExpiresAt()就是给exp赋值,withAudience()就是给aud赋值
/*** Add a specific Audience ("aud") claim to the Payload.** @param audience the Audience value.* @return this same Builder instance.*/public Builder withAudience(String... audience) {addClaim(PublicClaims.AUDIENCE, audience);return this;}/*** Add a specific Expires At ("exp") claim to the Payload.** @param expiresAt the Expires At value.* @return this same Builder instance.*/public Builder withExpiresAt(Date expiresAt) {addClaim(PublicClaims.EXPIRES_AT, expiresAt);return this;}
它们都调用了addClaim方法,可以看到就是在载荷的那个map中添加key和value
private void addClaim(String name, Object value) {if (value == null) {payloadClaims.remove(name);return;}payloadClaims.put(name, value);}
前面说过也可以自定义声明添加到载荷这部分,这里也提供了多个方法,这里展示两个
/*** Add a custom Claim value.** @param name the Claim's name.* @param value the Claim's value.* @return this same Builder instance.* @throws IllegalArgumentException if the name is null.*/public Builder withClaim(String name, Boolean value) throws IllegalArgumentException {assertNonNull(name);addClaim(name, value);return this;}/*** Add a custom Claim value.** @param name the Claim's name.* @param value the Claim's value.* @return this same Builder instance.* @throws IllegalArgumentException if the name is null.*/public Builder withClaim(String name, Integer value) throws IllegalArgumentException {assertNonNull(name);addClaim(name, value);return this;}
然后是sign()方法,这里这里传入了一个我们指明秘钥的算法,headerClaims.put方法给头部添加了令牌的类型(即 JWT)和正在使用的签名算法
/*** Creates a new JWT and signs is with the given algorithm** @param algorithm used to sign the JWT* @return a new JWT token* @throws IllegalArgumentException if the provided algorithm is null.* @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key.*/public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException {if (algorithm == null) {throw new IllegalArgumentException("The Algorithm cannot be null.");}headerClaims.put(PublicClaims.ALGORITHM, algorithm.getName());headerClaims.put(PublicClaims.TYPE, "JWT");String signingKeyId = algorithm.getSigningKeyId();if (signingKeyId != null) {withKeyId(signingKeyId);}return new JWTCreator(algorithm, headerClaims, payloadClaims).sign();}
然后new 了一个JWTCreator对象
private JWTCreator(Algorithm algorithm, Map<String, Object> headerClaims, Map<String, Object> payloadClaims) throws JWTCreationException {this.algorithm = algorithm;try {ObjectMapper mapper = new ObjectMapper();SimpleModule module = new SimpleModule();module.addSerializer(ClaimsHolder.class, new PayloadSerializer());mapper.registerModule(module);mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);headerJson = mapper.writeValueAsString(headerClaims);payloadJson = mapper.writeValueAsString(new ClaimsHolder(payloadClaims));} catch (JsonProcessingException e) {throw new JWTCreationException("Some of the Claims couldn't be converted to a valid JSON format.", e);}}
这里可以看到这两句代码,把头部这个map和载荷这个map都转换成了json串
headerJson = mapper.writeValueAsString(headerClaims);payloadJson = mapper.writeValueAsString(new ClaimsHolder(payloadClaims));
然后返回,在new一个JWTCreator对象后又调用了这个对象的sign()方法
private String sign() throws SignatureGenerationException {String header = Base64.encodeBase64URLSafeString(headerJson.getBytes(StandardCharsets.UTF_8));String payload = Base64.encodeBase64URLSafeString(payloadJson.getBytes(StandardCharsets.UTF_8));String content = String.format("%s.%s", header, payload);byte[] signatureBytes = algorithm.sign(content.getBytes(StandardCharsets.UTF_8));String signature = Base64.encodeBase64URLSafeString((signatureBytes));return String.format("%s.%s", content, signature);}
可以看到首先对header也就是头部做了base64编码,然后对载荷 payload也做了base64编码
String header = Base64.encodeBase64URLSafeString(headerJson.getBytes(StandardCharsets.UTF_8));
String payload = Base64.encodeBase64URLSafeString(payloadJson.getBytes(StandardCharsets.UTF_8));
然后使用小数点连接
String content = String.format("%s.%s", header, payload);
然后使用算法对连接后的头部和载荷进行签名,最后形成签名
byte[] signatureBytes = algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
然后用base64对签名进行编码,再把编码后的签名和前面的头部,载荷连接起来
String signature = Base64.encodeBase64URLSafeString((signatureBytes));return String.format("%s.%s", content, signature);
相关文章:
jwt的了解和使用以及大致代码分析
jwt简介 以下介绍来自官网(https://jwt.io/) SON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信…...
uniapp中videojs、renderjs的使用
在uniapp中使用了某些前端库或iframe,需要操作这些库中的dom的时候, 而uni上又没有document等基础对象。也就无法操作这些dom去实现一些交互逻辑,那么,涉及到这些的前端类库就无法使用,例如html2、canvas、image、vide…...

AIGC AI绘画 Midjourney 参数大全详细列表
AIGC ChatGPT 职场案例 AI 绘画 与 短视频制作, Power BI 商业智能 68集, 数据库Mysql8.0 54集 数据库Oracle21C 142集, Office 2021实战, Python 数据分析, ETL Informatica 案例实战 Excel 2021实操,函数大全,图表大全,大屏可视化制作 加技巧500集 数据分析可视化T…...

安装hadoop,并配置hue
0、说明 对于大数据学习的初始阶段,我也曾尝试搭建相应的集群环境。通过搭建环境了解组件的一些功能、配置、原理。 在实际学习过程中,我更多的还是使用docker来快速搭建环境。 这里记录一下我搭建hadoop的过程。 1、下载hadoop 下载地址:…...

23种经典设计模式:单例模式篇(C++)
前言: 博主将从此篇单例模式开始逐一分享23种经典设计模式,并结合C为大家展示实际应用。内容将持续更新,希望大家持续关注与支持。 什么是单例模式? 单例模式是设计模式的一种(属于创建型模式 (Creational Pa…...
ros中对move_base的调用
move_base包中自带costmap2d, global planner 等功能 也可以直接调用其中make_plan进行路径规划 #include "geometry_msgs/PoseStamped.h" #includde "nav_msgs/GetPlan.h"void fillPathRequest(nav_msgs::GetPlan::Request &request, float start_x…...

Git从本地库撤销已经添加的文件或目录
场景 在提交时, 误将一个目录添加到了暂存区, 而且commit 了本地库,同批次commit 的还有其他需要提交的文件。 commit 之后发现这个目录下所有的文件都不需要提交, 现在需要撤销这个提交, 使这个目录不被push到远端库。 这里以远端服务器github 为例,在Git GUI下看到的…...

百度SEO优化的特点(方式及排名诀窍详解)
百度SEO优化的特点介绍: 百度SEO优化是指对网站进行优化,使其在百度搜索引擎中获得更好的排名,进而获取更多的流量和用户。百度SEO优化的特点是综合性强、效果持久、成本低廉、投资回报高。百度的搜索算法不断更新,所以长期稳定的…...

Gin 文件上传操作(单/多文件操作)
参考地址: 单文件 | Gin Web Framework (gin-gonic.com)https://gin-gonic.com/zh-cn/docs/examples/upload-file/single-file/ 单文件 官方案例: func main() {router := gin.Default()// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)router.MaxMultipartMem…...

分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测
分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测 目录 分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现KOA-CNN-LSTM开普勒算法优化…...

Qt应用开发(基础篇)——列表视图 QListView
一、前言 QListView类继承于QAbstractItemView类,提供了一个列表或者图标视图的模型。 视图基类 QAbstractItemView QListView效果相当于Windows文件夹右键->查看->图标和列表,使用setViewMode()设置视图模式,并且提供setIconSize()函数…...

vue-6
一、声明式导航-导航链接 1.需求 实现导航高亮效果 如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!! 2.解决方案 vue-router 提供了一个全局组件 router…...

温度在线检测技术在电力电缆线路的应用
在电力电缆的日常运行检测中,针对电缆温度的状况,所采用的电力温度在线检测技术也得到了大范围的普及。电网系统中,其单位时间内可输送的电力能源受到其温度的变化影响。因此,采用更有效的方式实时检测电缆系统运行温度࿰…...

2023年中国自动化微生物样本处理系统竞争现状及行业市场规模分析[图]
微生物检测能够对感染性疾病的病原体或者代谢物进行检测分析,是IVD的细分领域之一。2022年中国体外诊断市场规模1424亿元。 2015-2022年中国体外诊断市场规模 资料来源:共研产业咨询(共研网) 微生物检测由于样本类型多样…...
硬链接和软连接的区别
软链接(也称为软连接或符号链接)是一种特殊的文件,其内容是另一个文件的路径。当你使用软链接时,实际上是在操作另一个文件。软链接的优点是它可以跨文件系统使用,因此可以跨分区或磁盘链接文件。此外,软链…...

保护隐私与增强网络安全之网络代理技术
目录 前言 一、网络代理技术原理 二、网络代理技术类型 1. HTTP代理 2. SOCKS代理 3. DNS代理 4. 加密代理 5. 反向代理 三、网络代理技术应用 1. 加速网络访问速度 2. 绕过网络限制 3. 保护个人隐私 4. 节省带宽 5. 改善网络安全 四、网络代理技术优缺点 网络…...
【每日一题】CF1680C. Binary String | 双指针 | 简单
题目内容 原题链接 给定一个长度为 n n n 的 01 01 01 字符串,对于一个子串 s u b sub sub ,子串内部的 0 0 0 的数量为 x x x ,子串以外的 1 1 1 的数量为 y y y ,子串的代价为 m a x ( x , y ) max(x, y) max(x,y) &…...

10.selenium进阶
文章目录 1、嵌套网页1、1 什么是嵌套页面1、2 selenium获取嵌套页面的数据 2、执行JavaScript代码3、鼠标动作链4、selenium键盘事件5、其他方法5、1 选择下拉框5、2 弹窗的处理 6、selenium设置无头模式7、selenium应对检测小结 1、嵌套网页 在前端开发中如果有这么一个需…...

【安全】 Java 过滤器 解决存储型xss攻击问题
文章目录 XSS简介什么是XSS?分类反射型存储型 XSS(cross site script)跨站脚本攻击攻击场景解决方案 XSS简介 跨站脚本( cross site script )为了避免与样式css(Cascading Style Sheets层叠样式表)混淆,所以简称为XSS。 XSS是一种经常出现在web应用中的计算机安全…...

一、Excel VBA 是个啥?
Excel VBA 从入门到出门一、Excel VBA 是个啥?二、Excel VBA 简单使用 👋Excel VBA 是个啥? ⚽️1. Excel 中的 VBA 是什么?⚽️2. 为什么 VBA 很重要?⚽️3. 是否有无代码方法可以在 Excel 中实现工作流程自动化&…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...