JWT | 一分钟掌握JWT | 概念及实例

news2024/11/26 13:32:58

作者:Mars酱

声明:本文章由Mars酱编写,部分内容来源于网络,如有疑问请联系本人。

转载:欢迎转载,转载前先请联系我!

什么是JWT

JWT的全称是Json Web Token。是基于RFC 7519开放标准的,它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以用作验证和相互信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSAECDSA 的公钥/私钥对进行签名。

哪里能用JWT

以下是JWT两种使用场景:

  • 授权:这是使用 JWT 的最常见的使用场景。用户登录后,每个后续请求都将包含 JWT,允许用户访问使用该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且能够跨不同域轻松使用。
  • 信息交换:JWT是在各方之间安全传输信息的比较便捷的方式。由于 JWT 可以签名(例如,使用公钥/私钥对),因此可以确定发送者是否是在您的授权范围之内。并且,由于签名是使用标头和有效负载计算的,因此还可以验证内容是否未被篡改。

JWT的组成

这是一个JWT的token串:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

很复杂,看不懂是不是?其实这一串是经过加密之后的密文字符串,中间通过.来分割。每个.之前的字符串分别表示JWT的三个组成部分:HeaderPayloadSignature

Header(头信息)

Header的主要作用是用来标识。通常是两部分组成:

  • typ:type 的简写,令牌类型,也就是JWT。
  • alg:Algorithm 的简写,加密签名算法。一般使用HS256,jwt官网提供了12种的加密算法,截图如下:

Header的明文示例:

{
  "alg": "HS256",
  "typ": "jwt"
}

经过Base64编码之后的明文,变为:

eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9

也就是第一个.之前的密文串。以下是Header部分常用部分的声明:

keyname说明
typ令牌类型如果存在,则必须将其设置为已注册的 IANA 媒体类型。
cty内容类型如果使用嵌套签名或加密,建议将其设置为 ;否则,请省略此字段。
alg消息身份验证代码算法发行者可以自由设置算法来验证令牌上的签名。但是,某些受支持的算法不安全。
kid密钥标识指示客户端用于生成令牌签名的密钥的提示。服务器将此值与文件上的密钥匹配,以验证签名是否有效以及令牌是否真实。
x5cx.509 证书链RFC4945 格式的证书链,对应于用于生成令牌签名的私钥。服务器将使用此信息来验证签名是否有效以及令牌是否真实。
x5ux.509 证书链网址服务器可在其中检索与用于生成令牌签名的私钥对应的证书链的 URL。服务器将检索并使用此信息来验证签名是否真实。
crit危急服务器必须理解的标头列表,以便接受令牌为有效令牌

Payload(负载信息)

也称为JWT claims,放置需要传输的信息,有三类:

  • 保留claims:主要包括iss发行者、exp过期时间、sub主题、aud用户等。
  • 公共claims:定义新创的信息,比如用户信息和其他重要信息。
  • 私有claims:用于发布者和消费者都同意以私有的方式使用的信息。

以下是Payload的官方定义内容:

keyname说明
iss发送者标识颁发 JWT 的发送主体。
sub主题标识 JWT 的主题。
aud接收者标识 JWT 所针对的接收者。每个在处理 JWT 的主体都必须使用受众声明中的值来标识自己。如果处理的主体在存在此声明时未将自己标识为声明中的值,则必须拒绝 JWT。
exp到期时间标识不得接受 JWT 进行处理的过期时间。该值必须是日期类型,而且是1970-01-01 00:00:00Z 之后的日期秒。
nbfjwt的开始处理的时间标识 JWT 开始接受处理的时间。该值必须是日期。
iatjwt发出的时间标识 JWT 的发出的时间。该值必须是日期。
jtijwt id令牌的区分大小写的唯一标识符,即使在不同的颁发者之间也是如此。

Payload明文示例:

{
  "sub": "12344321",
  "name": "Mars酱", // 私有claims
  "iat": 1516239022
}

经过Base64加密之后的明文,变为:

eyJzdWIiOiIxMjM0NDMyMSIsIm5hbWUiOiJNYXJz6YWxIiwiaWF0IjoxNTE2MjM5MDIyfQ

也就是第一个.和第二个. 之间的密文串内容。

Signatrue(签名信息)

Signature 部分是对Header和Payload两部分的签名,作用是防止 JWT 被篡改。这个部分的生成规则主要是是公式(伪代码)是:

Header中定义的签名算法(
    base64编码(header) + "." + base64编码(payload),
    secret
)

secret是存放在服务端加密使用到的盐。

得到签名之后,把Header的密文、Payload的密文、Signatrue的密文按顺序拼接成为一个字符串,中间通过.来连接并分割,整个串就是JWT了。

JWT实例

概念讲完了,我们来个实例吧,先来一个jwt的编码:

    public static String encodeJWT(String key) {
        // 1. 定义header部分内容 
        Map headerMap = new HashMap();
        headerMap.put("alg", SignatureAlgorithm.HS256.getValue());
        headerMap.put("typ", "JWT");

        // 2. 定义payload部分内容
        Map payloadMap = new HashMap();
        payloadMap.put("sub", "mars酱让你爽一分钟");
        payloadMap.put("iat", UUID.randomUUID());
        payloadMap.put("exp", System.currentTimeMillis() + 24 * 60 * 60 * 1000);
        payloadMap.put("name", "Mars酱");
        payloadMap.put("role", "酱油王");

        // 3.生成token
        String jwtToken = Jwts.builder()
                .setHeaderParams(headerMap)
                .setClaims(payloadMap)
                .signWith(SignatureAlgorithm.HS256, key)
                .compact(); // 拼接header + payload
//        System.out.println(jwtToken);
        return jwtToken;
    }

我们在main函数中调用这个,运行得到结果:

很长的密文字符串,就不截完整了。其中key是盐,jsonwebtoken的jar包规定,key必须字节数要大于等于你所用的加密算法的最小字节数,mars酱这里使用的是HS256,最小的key长度规定的就是256:

因此,key值我这里传入了一个超长的key:

String key = "marsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmarsmars";

如果你的key没这么长,你可能会报这样错误:

下面再来一个解密jwt的代码,入参为加密后的jwt和盐key:

    public static void decodeJWT(String jwtToken, String key) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(jwtToken)
                    .getBody();
            Object sub = claims.get("sub");
            Object name = claims.get("name");
            Object role = claims.get("role");
            Object exp = claims.get("exp");

            System.out.println("sub:" + sub + "\nname:" + name.toString() + "\nrole:" + role + "\nexp:" + exp + "\n失效了?" + ((System.currentTimeMillis() - (Long)exp) > 0));
        } catch (ExpiredJwtException e) {
            System.out.println("mars酱提醒您:token已过期");
        }
    }

在main中调用后,得到结果:

把生成的jwt字符串放入官网( jwt.io )的解密界面,和程序解密的结果一样,是不是很完美?

优缺点

好了,概念说完了,实例也给了,想想jwt有什么优缺点?我总结了一下:

优点:

  1. 可扩展性好 应用程序分布式部署的情况下,如果使用session机制,那就要要做多台机器的数据共享,通常可以存在数据库或者redis里面。而使用jwt不需要共享。
  2. jwt是无状态的 jwt不在服务端存储任何状态。RESTful API的原则之一是无状态,发出请求时,总会返回带有参数的响应,不会产生附加影响。用户的认证状态引入这种附加影响,这破坏了这一原则。另外jwt的载荷中可以存储一些常用信息,用于交换信息,有效地使用 JWT,可以降低服务器查询数据库的次数。

缺点:

  1. 安全性 由于jwt的payload是使用base64编码的,并没有加密,因此jwt中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全。
  2. 一次性 无状态是jwt的特点,但也导致了这个问题,jwt是一次性的。想修改里面的内容,就必须签发一个新的jwt。

jwt开源框架

mars酱这里使用的jwt是io.jsonwebtoken的,它需要在pom中引入依赖:

	<!-- jwt api定义 -->
	<dependency>
		<groupId>io.jsonwebtoken</groupId>
		<artifactId>jjwt-api</artifactId>
		<version>0.10.2</version>
	</dependency>
	<!-- jwt api impl实现 -->
	<dependency>
		<groupId>io.jsonwebtoken</groupId>
		<artifactId>jjwt-impl</artifactId>
		<version>0.10.2</version>
	</dependency>
	<!-- jwt json -->
	<dependency>
		<groupId>io.jsonwebtoken</groupId>
		<artifactId>jjwt-jackson</artifactId>
		<version>0.10.2</version>
	</dependency>

其余的jwt框架全在jwt官网列举了。基本覆盖了全语言

好好享受jwt的校验过程吧

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

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

相关文章

玩转ChatGPT:视频制作

一、写在前面 最近&#xff0c;在码深度学习图像识别的相关知识和代码&#xff0c;这一part&#xff0c;看看能否用小Chat搞一个介绍视频。 简单问小Chat&#xff1a; 咒语&#xff1a;我怎么使用你做一个视频&#xff1f;需要配合什么软件生成&#xff1f;&#xff1f; 大意…

2023.5.22-5.28 AI行业周刊(第149期):毕业10年后的实验室聚会

周末和实验室&#xff0c;无锡这边师兄弟们相聚了一次&#xff0c;之前在无锡这边的江南大学读书&#xff0c;后来工作后大家大多数也都留在了无锡。 我们研究生时的实验室&#xff0c;专门有一个微信群&#xff0c;从02年入学&#xff0c;到17年入学&#xff0c;多年各界的师…

Node.JS学习 | Babel | webpack | ES6

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Node.JS Node.JS能够在服务器端运行JavaScript的开放源代码、跨平台运行环境&#xff1b;Node.js采用Google开发的V8运行代码&#xff0c;使用事件驱动、非阻塞IO和异…

Python常用数据结构

Python 提供了多种内置的数据结构&#xff0c;用于存储和组织数据。以下是一些常见的 Python 数据结构&#xff1a; 1.列表&#xff08;List&#xff09;&#xff1a;列表是一个有序、可变的数据集合&#xff0c;可以包含任意类型的元素。列表使用方括号 [] 表示&#xff0c;元…

谷歌周彦祺:LLM浪潮中的女性科学家多面手丨智源大会嘉宾风采

导读 大模型研发竞赛如火如荼&#xff0c;谷歌紧随OpenAI其后推出PalM2、Gemini等系列模型。Scaling Law是否仍然适用于当下的大模型发展&#xff1f;科技巨头与初创企业在竞争中各有哪些优势和劣势&#xff1f;模型研究者应秉持哪些社会责任&#xff1f; 2023智源大会「基础模…

华为OD机试真题B卷 Java 实现【最长的连续子序列】,附详细解题思路

一、题目描述 有N个正整数组成的一个序列,给定一个整数sum,求长度最长的的连续子序列使他们的和等于sum,返回该子序列的长度,如果没有满足要求的序列返回-1。 二、输入描述 第1行有N个正整数组成的一个序列。 第2行给定一个整数sum。 求最长连续子序列,只要遍历计算连…

补贴平价好书影响上亿读者:有一种力量叫“至拙”

通过一种“至拙”的力量&#xff0c;“多多读书月”带来诸多可喜的变化。 全民拼书&#xff1a;“多多读书月”带来平价好书 如果你也是一位热爱读书的小伙伴&#xff0c;那么想来一定不会不知道“多多读书月”。 2020年&#xff0c;在“三区三州”地区助力脱贫攻坚的公益活动中…

转转前端周刊第六十七期

转转前端周刊 本刊意在将整理业界精华文章给大家&#xff0c;期望大家一起打开视野 如果你有发现一些精华文章想和更多人分享&#xff0c;可以点击我们的公众号名称&#xff0c;将文章链接和你的解读文案发给我们&#xff01;我们会对内容进行筛选和审核&#xff0c;保留你的推…

详细理解GPT2模型结构及其训练过程—GPT系列训练与部署

本文为博主原创文章&#xff0c;未经博主允许不得转载。 本文为专栏《Python从零开始进行AIGC大模型训练与推理》系列文章&#xff0c;地址为“https://blog.csdn.net/suiyingy/article/details/130169592”。 GPT2模型环境搭建与调试请参考博文《GPT系列训练与部署—GPT2环境配…

一分钟学一个 Linux 命令 - ls

前言 大家好&#xff0c;我是 god23bin。今天我给大家带来的是 Linux 命令系列&#xff0c;每天只需一分钟&#xff0c;记住一个 Linux 命令不成问题。今天&#xff0c;我们要介绍的是一个常用而又强大的命令&#xff1a;ls&#xff08;list&#xff09;。 什么是 ls 命令&am…

CVPR 2023 | 去雨去噪去模糊,图像low-level任务,视觉AIGC系列

Learning A Sparse Transformer Network for Effective Image Deraining 基于Transformer的方法在图像去雨任务中取得了显著的性能&#xff0c;因为它们可以对重要的非局部信息进行建模&#xff0c;这对高质量的图像重建至关重要。本文发现大多数现有的Transformer通常使用查询…

Linux的进程信号(下)

文章目录 1. 阻塞信号1.1 信号其他相关常见概念1.2 在内核中的表示 2. sigset_t3. 信号集操作函数3.1 sigprocmask3.2 sigpending3.3. 实例演示 4. 信号的处理4.1. sigaction4.2 多个信号的处理 5. 可重入函数6. volatile7. SIGCHLD信号 1. 阻塞信号 1.1 信号其他相关常见概念…

java基于springboot自来水收费缴费系统+jsp

本次设计拟采用JAVA技术&#xff0c;对乡镇自来水收费系统的功能需求进行了全面分析&#xff0c;从模块功能定义、前后端交互技术、数据库及编程语言的选择、系统调试及测试、功能完善和改进等方面进行设计&#xff0c;解决了从用户新装、抄表、计费、收费、复查、换表、发票管…

Pyside6-第三篇-QToolButton一个奇葩的按钮

今天是Pyside6的第三篇内容。一起来看另一个按钮。 QToolButton。 from PySide6.QtWidgets import QToolButton, QWidget, QApplicationapp QApplication([])win QWidget() win.setWindowTitle("QToolButton按钮")btn QToolButton(win) btn.setText("触发&qu…

Cell揭秘--慢性压力如何导致肠道炎症

大脑产生的信号传导到肠道神经细胞&#xff0c;导致炎症化学物质的释放。 溃疡性结肠炎患者的肠道组织&#xff08;人工着色&#xff09;。图片来源: Steve Gschmeissner/Science Photo Library 心理压力会加重某些肠道疾病引起的肠道炎症。现在&#xff0c;科学家们找到了原因…

初学QT(Day05)

继续第四天的demo 总结了之前的经验教训&#xff0c;我重新开一个项目项目&#xff0c;先给出demo的结果吧&#xff0c;第一张是第一次写的demo&#xff0c;第二张图是成品的demo 结果还是比较满意的&#xff0c;虽然过程中有遇到的问题不是我自己独立解决的。。。相比于第…

GPT-4能否取代数据分析师?达摩院的初步实验为你解答~

深度学习自然语言处理 原创作者 | 刘嘉玲 最近&#xff0c;数据分析师圈子大家在讨论GPT-4对他们的工作有什么影响&#xff1a;是替代还是辅助&#xff1f;个人认为GPT-4可以帮助我提高工作效率和质量。 要成为一名高级的数据分析师&#xff0c;需要经过长期的学习和实践&#…

无代码玩转GIS应用,我也在行【文末送书】

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

jQuery-图片跟随

<!DOCTYPE html > <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>图片跟随 </title> <style type"text/css"> body { text-align: center; …

【配电网重构】基于改进二进制粒子群算法的配电网重构研究(Matlab代码实现

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…