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 指…...

Git基础之分支
常用指令 git branch 列出本地所有分支 git branch -r 列出所有远程分支 git branch [branch-name] 新建一个分支,但依然停留在当前分支 git checkout -b [branch] 新建一个分支,并切换到该分支 git merge [branch] 合并指定分支当前分支 git branch -d …...

MAC电脑常用操作
环境:M3芯片 ,macOS15.2 🚀 快捷键 🖥️ 窗口管理 ✅ 退出/进入全屏模式 • 浏览器等应用:⌘ Command Ctrl F ✅ 最小化当前窗口 • ⌘ Command M • 💡 隐藏窗口但保留应用在后台运行 ✅ 关闭当前标…...

【计算机网络】深入解析 HTTP 协议的概念、工作原理和通过 Fiddler 抓包查看 HTTP 请求/响应的协议格式
网络原理— HTTP 1. 什么是HTTP? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议: HTTP 往往是基于传输层的 TCP 协议实现的 (HTTP1.0,HTTP1.1,HTTP2.0 均为TCP,HTTP3基于UDP实现) 我们平时打开一个网站,就是通过HTTP协议来…...

Springboot redis bitMap实现用户签到以及统计,保姆级教程
项目架构,这是作为demo展示使用: Redis config: package com.zy.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.Ob…...

【C++】:STL详解 —— 红黑树封装map和set
目录 红黑树的源代码 正向迭代器的代码 反向迭代器的代码 set的模拟实现 map的模拟实现 红黑树的源代码 #pragma once #include <iostream>using namespace std; // set ->key // map ->key/value// set ->key // map ->key/valueenum Colour {RED,BLAC…...

FPGA设计时序约束用法大全保姆级说明
目录 一、序言 二、时序约束概览 2.1 约束五大类 2.2 约束功能简述 2.3 跨时钟域约束 三、时序约束规范 3.1 时序约束顺序 3.2 约束的优先级 四、约束示例 4.1 设计代码 4.2 时序结果 4.2.1 create_clock 4.2.2 create_generated_clock 4.2.3 Rename_Auto-Derive…...

【前缀和与差分 C/C++】洛谷 P8218 求区间和
2025 - 03 - 09 - 第 72 篇 Author: 郑龙浩 / 仟濹 【前缀和与差分 C/C】 文章目录 洛谷 P8218 求区间和题目描述输入格式输出格式输入输出样例 #1输入 #1输出 #1 说明/提示思路代码 洛谷 P8218 求区间和 题目描述 给定 n n n 个正整数组成的数列 a 1 , a 2 , ⋯ , a n a_…...

C++修炼之路:初识C++
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 引言 …...

Pytorch 第九回:卷积神经网络——ResNet模型
Pytorch 第九回:卷积神经网络——ResNet模型 本次开启深度学习第九回,基于Pytorch的ResNet卷积神经网络模型。这是分享的第四个卷积神经网络模型。该模型是基于解决因网络加深而出现的梯度消失和网络退化而进行设计的。接下来给大家分享具体思路。 本次…...

2025-3-9 一周总结
目前来看本学期上半程汇编语言,编译原理,数字电路和离散数学是相对重点的课程. 在汇编语言和编译原理这块,个人感觉黑书内知识点更多,细节更到位,体系更完整,可以在老师讲解之前进行预习 应当及时复习每天的内容.第一是看书,然后听课,在一天结束后保证自己的知识梳理完整,没有…...