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 指…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
