JWT的学习
1、HTTP无状态及解决方案
HTTP一种是无状态的协议,每次请求都是一次独立的请求,一次交互之后就是陌生人。
以CSDN为例,先登录一次,然后浏览器退出,这个时候在进入CSDN,按理说服务器是不知道你已经登陆了,所以需要你重新登录,但实际却是再次点进来之后,仍然保持登录状态。
这是因为解决了HTTP无状态这个问题,解决方式有很多:
①使用Session和Cookie,将 无状态 变为 有状态
第一次请求时,服务器会自动记录一个SessionId,然后把SessionId返回给浏览器。再次发起请求时,浏览器就会携带SessionId,而服务器就可以根据SessionId,去查询会话信息(session)。
服务器可以往会话里保存用户信息

浏览器会自动保存SessionId
![]()
Session弊端:Session和Cookie适用于单机环境,默认情况下会话信息(session)是保存在服务器内存中,用户量大的话,服务器内存压力大。如果生产是集群环境,就没办法保证浏览器的请求每一次都传到有会话信息的那一台服务器。
这种也好解决,把会话信息存到Redis里,每次访问,服务器根据SessionId,去Redis拿会话信息(SpringBoot实现了这个功能,引入【spring-session-data-redis】依赖包,做一些设置,就会自动将会话信息交给Redis管理),这样做服务器的内存压力也就会见。
②使用Token
在登录时,生成一个Token放入Redis,之后把token返回给浏览器。浏览器发起其他请求时,携带这个token,服务器再去Redis看这个Token是否失效之类的。
③使用JWT
使用JWT和使用Token很像,但JWT不需要存储到Redis,就能通过验签,知道用户信息是否伪造、用户登录状态是否过期等等。
2、JWT的基本介绍
JWT官网地址:https://jwt.io/
JWT,全称JSON WEB TOKEN,是一种JSON格式的Web应用令牌,它是基于令牌去做认证。
什么是令牌,举个例子,古代调兵用的虎符,这就相当于是令牌,有了虎符,才能调兵。而令牌也是,有了令牌,才能访问后端接口。
以下是官网介绍

大致就是JWT能够通过HMAC算法(默认算法),或者通过RSA、ECDSA算法生成数字签名(Signature)。
JWT令牌的组成

JWT由三部分组成:Header(头)、Payload(负载)、Signature(签名),三部分用 "." 进行分隔
Header
两部分组成:令牌的类型是什么,签名(Signature)使用什么算法。
从官网复制的例子,表示令牌的类型是JWT,算法是 HMAC-SHA256
{"alg": "HS256","typ": "JWT" }
Header的JSON串经过Base64编码就转换成 "x.y.z" 的 "x"部分
Payload
负载有七个默认字段
iss:发行人
exp:到期时间
sub:主体
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
官方样例如下:name 和 admin为自定义的字段
{"sub": "1234567890","name": "John Doe","admin": true
}
负载里面可以放自定义字段,这部分内容也是通过Base64编码变成"x.y.z"部分的"y"部分,可以通过Base64解码,拿到里面的信息。所以,官方也推荐不要往负载里存放敏感信息,比如密码之类的,除非想故意被攻击。
Signature
官方提供的例子如下,可以看见,签名是通过前两部分(Header 和 Payload)base64编码之后的字符串拼接成一个新的字符串,以及指定一个密钥(secret),并使用Header里指定的算法生成的签名。因此,密钥是一定不能暴露出去的。
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
假如攻击者对前两部分进行随意修改,并冒充前端发起请求。后端每次验签的时候,都会根据前两部分内容,加上密钥(secret),再去生成一次签名,而由于攻击者修改了内容,所以生成的签名肯定和传来的签名不匹配,这就说明被篡改了,从而验签失败。

3、JWT的优缺点
优点
1、JWT生成的令牌保存在客户端(前端),服务端不会保存令牌,减少了服务器内存的损耗。
2、易扩展,负载中可以保存自定义的信息。
3、使用强密钥生成签名时,JWT提供了很好的安全性。
4、使用JWT,HTTP仍是无状态的,和Session、Cookie的方式正好相反,JWT不需要在服务器存储会话信息,非常适合集群环境。
缺点
1、JWT 本身不支持会话管理,不能主动使令牌失效。假如用户修改了密码,这个时候肯定要重新登录,原先的JWT令牌按理就应该失效,但是,由于没有到令牌指定的过期时间,所以原先的令牌仍然是有效的。(可以将令牌存到redis,当修改密码后删除令牌,当令牌没有就强制用户去登录)
2、负载(Payload)中存放过多用户数据时,会影响性能。
4、如何使用JWT
大致流程:用户通过前端页面进行登录,业务校验通过之后,生成一个令牌(JWT),后端将JWT返回给前端,前端进行保存。之后,前端每次访问后端,都必须携带JWT,后端去验证令牌(JWT)的合法性。
①导入JWT依赖
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version>
</dependency>
②编写工具类,生成令牌
前面提到了,JWT令牌由三部分组成,所以创建一个JWT令牌,只要保证有这三部分就可以了
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;import java.util.Base64;
import java.util.Calendar;
import java.util.HashMap;public class JWTUtil {//密钥,一般是从配置文件读取private static final String secretKey = "4008123123@#";private static final String algorithm = Algorithm.HMAC256(secretKey).getName();/*** 生成JWT令牌** @return*/public static String generateJwtToken(String userId, String secretKey) {Calendar exp = Calendar.getInstance();//过期时间:当前时间往后推20分钟exp.add(Calendar.MINUTE, 20);System.out.println("过期时间:" + exp.getTime());// HashMap<String, Object> map = new HashMap<String, Object>();
// map.put("alg",algorithm);
// map.put("typ","JWT");String token = JWT.create()//header,即使不写,也会使用默认的推荐算法HS256和JWT令牌类型
// .withHeader(map).withExpiresAt(exp.getTime()) //默认的负载字段,设置过期时间.withClaim("userId", userId) //负载---自定义字段.withClaim("username", "UMR123") //负载---自定义字段.sign(Algorithm.HMAC256(secretKey));System.out.println(token);return token;}/*** 验签(验证JWT令牌的合法性)** @param jwtToken* @param secretKey* @return 用来获取令牌信息*/public static DecodedJWT verifyToken(String jwtToken, String secretKey) {//生成验证对象JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secretKey)).build();//如果验证没问题,就可以获取到负载信息,如果签名有问题(签名不一致,令牌过期),就会报错DecodedJWT verify = jwtVerifier.verify(jwtToken);System.out.println("负载(Payload)经过base64解码:" + new String(Base64.getDecoder().decode(verify.getPayload())));System.out.println("userId信息:" + verify.getClaim("userId").asString());System.out.println("username信息:" + verify.getClaim("username").asString());System.out.println("令牌过期时间:" + verify.getExpiresAt());return verify;}public static void main(String[] args) {//生成令牌String jwtToken = generateJwtToken("user123", secretKey);System.out.println();verifyToken(jwtToken, secretKey);}
}
控制台打印结果如下:

服务端生成JWT令牌之后,客户端在请求其他接口时,请求头新增Authorization字段,放入JWT信息
Authorization: Bearer <token>

都是对数据完整性和用户身份进行校验,什么时候直接使用算法生成签名,什么时候使用JWT?
当需求没有要求过期时间,就可以使用直接使用算法,反之,用JWT令牌是最好的。
相关文章:
JWT的学习
1、HTTP无状态及解决方案 HTTP一种是无状态的协议,每次请求都是一次独立的请求,一次交互之后就是陌生人。 以CSDN为例,先登录一次,然后浏览器退出,这个时候在进入CSDN,按理说服务器是不知道你已经登陆了&…...
elasticsearch是哪家的
Elasticsearch:数据搜索与分析的领航者 在当今这个信息爆炸的时代,快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…...
《A++ 敏捷开发》- 18 软件需求
需求并不是关于需求 (Requirements are not really about requirements) 大家去公共图书馆寄存物品,以前都是扫二维码开箱,有些图书馆升级了使用指纹识别。 “是否新方法比以前好?”我问年轻的开发人员。 “当然用指纹识别好。新技术&#x…...
计算机网络:计算机网络的组成和功能
计算机网络的组成: 计算机网络的工作方式: 计算机网络的逻辑功能; 总结: 计算机网络的功能: 1.数据通信 2.资源共享 3.分布式处理:计算机网络的分布式处理是指将计算任务分散到网络中的多个节点(计算机或设备&…...
Upload-Labs-Linux 1-20
前端校验绕过:pass 01 两种思路:1.通过抓包,修改后缀 2.前端禁用js绕过前端后缀检验 首先写一个木马,改为图片格式GIF89a<?php eval($_POST[cmd])?>抓包之后改为PHP格式: 使用蚁剑连接木马,第一次尝…...
Compose笔记(八)--权限
这一节主要了解一下Compose中权限的申请,其中主要用到accompanist-permissions这个权限库,它是一个简化的Android Compose 中权限管理的库,如下使用: 栗子: 依赖添加 dependencies {implementation("com.google.accompani…...
单例模式:确保一个类只有一个实例
目录 引言 1. 单例模式的核心思想 2. 单例模式的实现方式 2.1 饿汉式单例 2.2 懒汉式单例 2.3 线程安全的懒汉式单例 2.4 双重检查锁定(Double-Checked Locking) 2.5 静态内部类实现单例 2.6 枚举实现单例 3. 单例模式的使用场景 4. 单例模式…...
推荐一个好用的在线文本对比网站 - diffchecker
推荐网址:https://www.diffchecker.com UI设计也很不错,响应也很快,广告少 生成的对比还可以生成在线链接:(点击右上角“分享”) 可设置过期时间等 我生成的示例:https://www.diffchecker.c…...
学习第八十五行
[capture](parameters) -> return_type {// function body }capture: 捕获列表,指定如何捕获周围作用域中的变量。parameters: 参数列表,与普通函数类似。return_type: 返回类型,可以省略,编译器会自动推断。function body: 函…...
基于Django创建一个WEB后端框架(DjangoRestFramework+MySQL)流程
一、Django项目初始化 1.创建Django项目 Django-admin startproject 项目名 2.安装 djangorestframework pip install djangorestframework 解释: Django REST Framework (DRF) 是基于 Django 框架的一个强大的 Web API 框架,提供了多种工具和库来构建 RESTf…...
【Python 2D绘图】Matplotlib绘图(统计图表)
【Python 2D绘图】Matplotlib绘图(统计图表) 1. 概述1.1 简介1.2 安装1.3 导入1.4 保存1.5 数据来源1.5.1 Numpy ndarray1.5.2 Pandas DataFrame 1.6 中文显示 2. 基础样式2.1 颜色2.1.1 简称2.1.2 全称 2.2 布局2.2.1 Matplotlib 画布划分2.2.2 绘制子图…...
vue3框架的响应式依赖追踪机制
当存在一个响应式变量于视图中发生改变时会更新当前组件的所以视图显示,但是没有视图中不写这个响应式变量就就算修改该变量也不会修改视图,这是为什么?我们能否可以理解宽泛的理解为vue组件的更新就是视图的更新,单当视图中不存在…...
.Net 6 上传文件接口 文件大小报错整体配置
/// <summary>/// 上传文件/// </summary>/// <param name"file"></param>/// <returns></returns>[HttpPost("UploadifyFile")][RequestSizeLimit(2000 * 1024 * 1024)] // 设置最大请求体大小为 100MBpublic async …...
Git基础之工作原理
基础概念 git本地有三个工作区域,工作目录 Working Directory,暂存区Stage/Index和资源区Repository/Git Directory,如果在加上远程的git仓库就是四个工作区域 四个区域与文件交换的命令之间的关系 WorkSpace:工作区,就…...
小程序 wxml 语法 —— 41列表渲染 - 进阶用法
这一节讲解列表渲染的两个进阶用法: 如果需要对默认的变量名和下标进行修改,可以使用 wx:for-item 和 wx:for-item: 使用 wx:for-item 可以指定数组当前元素的变量名使用 wx:for-index 可以指定数组当前下标的变量名 将 wx:for 用在 标签上&…...
ElasticSearch 入门教程
ElasticSearch 入门教程 ElasticSearch 是一个分布式、可扩展的搜索和分析引擎,基于 Apache Lucene 构建,支持全文检索、结构化查询和聚合分析。本教程将带你深入了解 ElasticSearch 的核心概念、安装配置、常见操作,并提供示例代码…...
用Python写一个算24点的小程序
一、运行界面 二、显示答案——递归介绍 工作流程: 1. 基本情况:函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字,它会判断这个数字是否接近 24(使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题&…...
分布式网络
分布式网络(Distributed Network)指的是一种计算机网络架构,其中计算资源(计算、存储、数据处理等)分布在多个物理或逻辑上的节点上,而不是集中在单一的服务器或数据中心中。这种架构的主要目标是提高系统的…...
忘记dedecms后台超级管理员账号和密码的解决方案
解决方案: 方案一、数据库修改: 1、前提是您能登录到数据库后台,登录MySQL数据库管理工具(如phpMyAdmin) 2、打开数据库中的 dede_admin 表,找到管理员记录,将 pwd 字段的值改成 f297a57a5a7…...
【Linux学习笔记】Linux基本指令分析和权限的概念
【Linux学习笔记】Linux基本指令分析和权限的概念 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 文章目录 【Linux学习笔记】Linux基本指令分析和权限的概念前言一. 指令的分析1.1 alias 指令1.2 grep 指令1.3 zip/unzip 指…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
