springboot2入门到实战 - JWT

news2025/2/24 12:08:02

JWT是什么?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object。

This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

  • 基于JSON格式用于网络传输的令牌。
  • 紧凑的Claims声明格式。
  • Claim有索赔、声称、要求或者权利要求的含义。

在JWT之前

在JWT技术大规模应用之前,使用cookie+session技术做交互验证、存储由来已久。尤其在单体结构中更加突出(即使现在好多单体架构的项目依然使用cookie+session的经典组合)。

cookie+session技术之所以产生是由于HTTP协议在创建之初为加快服务器的响应,采用“无记忆性“来提高服务器的响应。但是会产生一系列的问题。例如:服务器如何确定客户端已经连接,已经登录了系统多长时间,是否允许该用户继续访问,该用户是否任然活跃,该用户如何找到其私有信息等问题等。
为此cookie+session技术很好的补充了http协议中“无记忆性“的问题。解决方案如图。

  • 服务器产生存储session对象,每个session对象有唯一的ID,有存活时间,可以记录数据。
  • 发起请求后,服务器将session的id写入客户端(浏览器),客户端通过cookie记录session的id
  • 客户端每一次发起请求需要携带session的id。
  • 服务器根据session的id查询指定session是否存在,然后交互。

image-20231026152201240

cookie-session模型很好的补充了http协议的无记忆性问题,但是如果在分布式环境下,如果每个服务器产生一个session或同步已有的session很困难,如果网络,服务器等由于延迟保证数据一致性比较困难。
为此我们需要一种轻量级,在分布式情况下依然能使用的技术尤为重要,JWT技术由此产生。

jwt的结构

image-20230515144726146

xxx.yyy.pppp

Header 部分是一个 JSON 对象,描述 JWT 的元数据。

image-20230515153047351

加密算法
  • HSA256

    SHA(Secure Hash Algorithm,安全散列算法)是一个密码散列函数家族,由美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)发布,是美国的政府标准。

    • 无论输入多长,都输出64个字符,共32字节(byte),256位(bit)
    • 输出只包含数字0`9`和字母`A`F,大小写不敏感
  • RSA256

    由美国麻 省理工 学院三 位学者 Riv est、Sh amir 及Adleman 研 究发 展出 一套 可实 际使用 的公 开金 钥密码系 统,那 就是RSA(Rivest-Shamir-Adleman)密码系统。

    RS256(带有SHA-256的 RSA 签名)是一种非对称算法,它使用公钥/私钥对:身份提供者拥有用于生成签名的私钥(秘密)密钥,而 JWT 的消费者获得公钥验证签名。由于与私钥相反,公钥不需要保持安全,因此大多数身份提供者都可以让消费者轻松获取和使用(通常通过元数据 URL)。

Base64

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。Base64不是加密算法,只是一种编码方式,可以用Base64来简单的“加密”来保护某些数据,所以每 6 个比特为一个单元,对应某个可打印字符。

image-20230515195043903

“hello” 编码

h–01101000 e --01100101

01101000

image-20230515201422170

 String str="hello";
        byte[] encode = Base64.getEncoder().encode(str.getBytes());
        String s = new String(encode);
        System.out.println("base64编码: "+s);

        byte[] decode = Base64.getDecoder().decode(s);
        String x = new String(decode);
        System.out.println("解析:" + x);

Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

Payload 也使用BASE64编码

Registered claims

这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行者),exp(到期时间),sub(主题),aud(受众)等

序号名称解释
1iss (issuer)签发人
2exp (expiration time)过期时间
3sub (subject)主题
4aud (audience)受众(接收jwt的一方)
5nbf (Not Before)生效时间
6iat (Issued At)签发时间
7jti (JWT ID)jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
Public claims

这些可以由使用JWT的人员随意定义。

Private claims

这些是为了同意使用它们但是既没有登记,也没有公开声明的各方之间共享信息,而创建的定制声明。

Payload案例
{
  "sub": "456781234",
  "name": "Mr.zhang",
  "admin": true
}

Signature

The signature is used to verify the message wasn’t changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.

Signature 部分是对前两部分的签名,防止数据篡改。

https://jwt.io/

Signature部分由编码后的Header、Payload和自定义的秘钥使用Header中指定的算法(HSA256)进行加密签名;

image-20230516085001222

image-20230516142821824

JWT构成

image-20230516085933230

jwt使用

maven中引入token依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.3.0</version>
</dependency>

创建token字符串

//数据
User user = new User(1, "tom", "123", "tomcat");
Map<String, String> map = new HashMap<>();
map.put("username", user.getUsername());
map.put("name", user.getName());


String token = JWT.create()
        .withAudience(user.getUsername())
        .withExpiresAt(new Date(System.currentTimeMillis()+1000*30)) //设置过期时间为30ms
        .withClaim("data", map)
        .sign(Algorithm.HMAC256(user.getPassword()));

输出token结果:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ0b20iLCJkYXRhIjp7ImFtZSI6InRvbWNhdCIsInVzZXJuYW1lIjoidG9tIn0sImV4cCI6MTY4NDIyNTk5NX0.oLSSNY9JeBRrKilOroUZ_xT5AS7AODotUxBXeOZ_D40

解析token

DecodedJWT decode = JWT.decode(token);

获取token的内容

System.out.println("Header: " + decode.getHeader());
System.out.println("Payload: " + decode.getPayload());
System.out.println("Audience: " + decode.getAudience());
System.out.println("Signature: " + decode.getSignature());

验证token

JWTVerifier build = JWT.require(Algorithm.HMAC256(user.getPassword())).build();

获取信息

System.out.println(build.verify(token).getClaim("data"));

{“name”:“tomcat”,“username”:“tom”}

token出现的问题

私钥salt被人篡改

  String salt ="guess";
    String token = JWT.create()
            .withClaim("name", "jack")
            .withClaim("password","123")
            .sign(Algorithm.HMAC256(salt));
    System.out.println(token);

    JWTVerifier build = JWT.require(Algorithm.HMAC256("abc")).build();
    build.verify(token);
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMyIsIm5hbWUiOiJqYWNrIn0.ghK3Y79d1VU66eaay9YknYyW9MhWCrsth93UTx75-fk
Exception in thread "main" com.auth0.jwt.exceptions.SignatureVerificationException: The Token's Signature resulted invalid when verified using the Algorithm: HmacSHA256
	at com.auth0.jwt.algorithms.HMACAlgorithm.verify(HMACAlgorithm.java:57)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:463)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:445)
	at com.wnhz.bms.preview.jwt.JwtDemo.main(JwtDemo.java:19)

篡改token中的信息

     String salt ="guess";
        String token = JWT.create()
                .withClaim("name", "jack")
                .withClaim("password","123")
                .sign(Algorithm.HMAC256(salt));
        System.out.println(token);

        token = token.replace("eyJwYXNzd29yZCI6IjEyMyIsIm5hbWUiOiJqYWNrIn0","eyJwYXNzd29yZCI7IjEyMyIsIm5hbWUiOiJqYWNrIn0");

        
      // token =  token.replace("K","W");//黑客

       // JWTVerifier build = JWT.require(Algorithm.HMAC256("abc")).build();
       JWTVerifier build = JWT.require(Algorithm.HMAC256(salt)).build();
        build.verify(token);
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMyIsIm5hbWUiOiJqYWNrIn0.ghK3Y79d1VU66eaay9YknYyW9MhWCrsth93UTx75-fk
Exception in thread "main" com.auth0.jwt.exceptions.JWTDecodeException: The string '{"password";"123","name":"jack"}' doesn't have a valid JSON format.
	at com.auth0.jwt.impl.JWTParser.decodeException(JWTParser.java:90)
	at com.auth0.jwt.impl.JWTParser.parsePayload(JWTParser.java:47)
	at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:49)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:444)
	at com.wnhz.bms.preview.jwt.JwtDemo.main(JwtDemo.java:26)

token过期

        String salt ="guess";
        String token = JWT.create()
                .withClaim("name", "jack")
                .withClaim("password","123")
                .withExpiresAt(new Date(System.currentTimeMillis()+10))
                .sign(Algorithm.HMAC256(salt));
        System.out.println(token);

        Thread.sleep(1000);

       JWTVerifier build = JWT.require(Algorithm.HMAC256(salt)).build();
        build.verify(token);
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMyIsIm5hbWUiOiJqYWNrIiwiZXhwIjoxNjk4MzA4MTA1fQ.KGA8e6HhO3CSxanvhBaO9X2EpCQY20iZCn2fkSqdlNo
Exception in thread "main" com.auth0.jwt.exceptions.TokenExpiredException: The Token has expired on 2023-10-26T08:15:05Z.
	at com.auth0.jwt.JWTVerifier$BaseVerification.assertValidInstantClaim(JWTVerifier.java:346)
	at com.auth0.jwt.JWTVerifier$BaseVerification.lambda$addMandatoryClaimChecks$17(JWTVerifier.java:308)
	at com.auth0.jwt.JWTVerifier$BaseVerification$1.verify(JWTVerifier.java:405)
	at com.auth0.jwt.JWTVerifier.verifyClaims(JWTVerifier.java:482)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:464)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:445)
	at com.wnhz.bms.preview.jwt.JwtDemo.main(JwtDemo.java:23)

使用拦截器统一拦截方式

@Component
public class AuthInterceptor  implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("bm_token");

        if (Objects.isNull(token) || "".equals(token.trim())) {
            throw new UserNoLoginException("用户名还没有登录异常");
        }

        return true;
    }
}

@Configuration
public class BmWebConfig implements WebMvcConfigurer {

    @Resource
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(authInterceptor)
                .excludePathPatterns("/api/login");

    }
}

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

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

相关文章

便签软件哪个好用?好用便签怎么设置提醒?

在当今信息爆炸的时代&#xff0c;便签软件成为了人们生活中不可或缺的工具之一。那么&#xff0c;便签软件哪个好用呢&#xff1f;下面为您推荐几款备受好评的便签软件。首先是知名度极高的好用便签&#xff0c;它拥有强大的笔记功能、提醒功能和多端同步&#xff0c;让您随时…

COMPOSER安装使用WIN下升级PHP-V

想用TP6使用phpspreadsheet但是说我PHP版本低&#xff0c;原来是PHP7.0 composer要求至少7.4 直接修改环境变量&#xff0c;把PHP目录切换到7.4 composer升级比较简单&#xff0c;在PHP目录下CMD然后官网的命令执行下即可 下面就可以在TP根目录下执行命令安装PHPSPREADSHEET…

Java进阶-集合(3)与泛型

这次介绍集合中的Iterator迭代器&#xff0c;以及泛型。简单来说&#xff0c;泛型对集合的元素类型进行了限制&#xff0c;使用泛型可以在编译时检查类型安全&#xff0c;提高代码的重用率。内容如下 一、Iterator迭代器 1、概念 Iterator迭代器是一个接口&#xff0c;作用…

MATLAB环境下脑电信号EEG的谱分析

脑电信号一直伴随着人类的生命&#xff0c;脑电波是脑神经细胞发生新陈代谢、离子交换时细胞群兴奋突触电位总和&#xff0c;脑电信号的节律性则和丘脑相关&#xff0c;含有丰富的大脑活动信息。通常我们所接触的脑电图都是头皮脑电图&#xff0c;在有些特殊场合还需要皮下部位…

TikTok网络相关问题详解来了,附原生住宅代理IP供应商推荐,

想要迈过TikTok新手门槛&#xff0c;首先必须要学习的就是网络问题。很多人开始做TikTok账号或者TikTok小店时&#xff0c;都会遇到一些先前没有遇到的词汇和概念&#xff0c;比如原生IP&#xff0c;独享IP&#xff0c;甚至专线&#xff0c;那么一个IP可以做几个账号呢&#xf…

0粉低成本带货!职人号矩阵正成为商家的香饽饽

近年来&#xff0c;中国消费市场变化不断&#xff0c;线上消费持续上涨&#xff0c;线上线下一体化成为零售行业的发展新趋势。 加上抖音等平台都在大力发展本地生活&#xff0c;众多连锁商家、本地商家、百货商场纷纷加快数字化转型步伐&#xff0c;掘金线上海量流量&#xff…

机器学习:原理、应用与未来展望

第一章 是什么 机器学习&#xff08;Machine Learning&#xff09;是一门跨学科的学科&#xff0c;它使用计算机模拟或实现人类学习行为&#xff0c;通过不断地获取新的知识和技能&#xff0c;重新组织已有的知识结构&#xff0c;从而提高自身的性能。机器学习涉及多个学科&am…

HGAME 2024 WEEK4 WP

文章目录 IOTez7621 MISCezKeyboardMaybezip**Mondrians &#x1f511; REchange webReverse and Escalation. 想念21和22年的平台和week4的 6557225了 IOT ez7621 拿到固件直接binwalk解&#xff0c;之后grep出hgame 在usr/lib/opkg/info/kmod-flag.control找到这个&#x…

Quartz 任务调度框架源码阅读解析

概念: quartz 是一个基于JAVA的定时任务调度框架 案例: <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>JobDetail job JobBuilder.newJob(Sc…

TP6上传图片到OSS(记录贴)

1&#xff0c;先安装&#xff0c;我使用composer安装 在项目的根目录运行composer require aliyuncs/oss-sdk-php 2,安装成功以后vendor目录下可以看到如图&#xff1a; 3&#xff0c;上传图片代码如下&#xff1a; <?php namespace app\controller;use app\BaseControll…

宝塔FTP服务设置并结合cpolar内网穿透实现远程传输文件

文章目录 1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 宝塔FTP是宝塔面板中的一项功能&#xff0c;用于设置和管理FTP服务。通过宝塔FTP&#xff0c;用户可以创建FTP账号&#xff0c;配置FTP用户权限…

D*算法超详解 (D星算法 / Dynamic A*算法/ Dstar算法)(死循环解决--跟其他资料不一样奥)

所需先验知识&#xff08;没有先验知识可能会有大碍&#xff0c;了解的话会对D*的理解有帮助&#xff09;&#xff1a;A*算法/ Dijkstra算法 何为D*算法 Dijkstra算法是无启发的寻找图中两节点的最短连接路径的算法&#xff0c;A*算法则是在Dijkstra算法的基础上加入了启发函数…

数据抽取平台pydatax介绍--实现和项目使用

数据抽取平台pydatax实现过程中&#xff0c;有2个关键点&#xff1a; 1、是否能在python3中调用执行datax任务&#xff0c;自己测试了一下可以&#xff0c;代码如下&#xff1a; 这个str1就是配置的shell文件 try:result os.popen(str1).read() except Exception as …

吴恩达机器学习全课程笔记第四篇

目录 前言 P61-P68 激活函数 Softmax算法 P69-P73 Adam算法 更多类型的层 模型评估 P74-P79 偏差和方差 建立表现基准 学习曲线 偏差和方差与神经网络 前言 这是吴恩达机器学习笔记的第四篇&#xff0c;第三篇笔记请见&#xff1a; 吴恩达机器学习全课程笔记第…

ubuntu20.04 ROS-Noetic 配置qtcreator的ROS环境

文章目录 1 安装qtcreator1.1 下载安装Qt1.2 配置命令启动qtcreator2 配置ROS2.1 直接安装qtcreator-ros2.2 在qtcreator上安装ros_qtc_plugin插件3 注意3.1 构建套件3.2 更新、删除qt4 参考链接1 安装qtcreator QT官网:Qt Downloads 下载包链接:qt5.12.12 Qt5.12.12默认qtc…

如何系统性的学习推荐系统?

推荐一本适合推荐系统、计算广告、个性化搜索领域的从业人员阅读的书&#xff1a;《互联网大厂推荐算法实战》。快手公司算法专家10余年的实战经验总结。涵盖一线互联网公司当前采用的主流推荐算法&#xff0c;凸显可用性、实用性提供从算法基本原理&#xff0c;到技术框架再到…

0代码自动化测试:RF 框架实现企业级 UI 自动化测试!

RobotFramework框架可以作为公司要做自动化 但是又不会代码的一种临时和紧急情况的替代方案&#xff0c;上手简单。 前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多人…

qml 项目依赖

文章目录 出现的问题最终对比下一步 把 apptestQml3_6.exe 放到一个单独目录下&#xff0c;执行 windeployqt.exe ./apptestQml3_6.exe但是出了很多问题&#xff0c;根本运行不起来。 但是在release目录下执行下&#xff0c;程序能跑起来。 根据错误提示&#xff0c;进行添加。…

浮点数二分(一个数开根号)

#include<iostream> using namespace std; int main(){double x;cin>>x;double l0,rx;while(r-l>1e-8){double mid(lr)/2;if(mid*mid>x)rmid;else lmid;}cout<<l<<endl;return 0; }

IJCAI 2023 |时空数据(Spatial-Temporal)论文

本次IJCAI 2023共收到4566份投稿&#xff0c;接收率大约15%&#xff0c;本文总结了IJCAI 2023有关时空数据&#xff08;spatial-temporal&#xff09;的论文。 时空数据Topic:轨迹异常检测&#xff0c;时空预测&#xff0c;信控优化等。 目录 Open Anomalous Trajectory Reco…