JWT令牌详解

JWT令牌

介绍

JWT全称:JSON Web Token (官网:https://jwt.io/)

定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

简洁:是指jwt就是一个简单的字符串。可以在请求参数或者是请求头当中直接传递。 自包含:指的是jwt令牌,看似是一个随机的字符串,但是我们是可以根据自身的需求在jwt 令牌中存储自定义的数据内容。如:可以直接在jwt令牌中存储用户的相关信息。 简单来讲,jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在 通信双方安全的进行信息传输了。

JWT的组成:

(JWT令牌由三个部分组成,三个部分之间使用英文的点来分割) 第一部分:Header(头), 记录令牌类型、签名算法等。 例如: {“alg”:“HS256”,“type”:“JWT”} 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如: {“id”:“1”,“username”:“Tom”} 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加 入指定秘钥,通过指定签名算法计算而来。

签名的目的就是为了防jwt令牌被篡改,而正是因为jwt令牌最后一个部分数字签名的存在, 所以整个jwt 令牌是非常安全可靠的。一旦jwt令牌当中任何一个部分、任何一个字符被篡 改了,整个令牌在校验的时候都会失败,所以它是非常安全可靠的。

image-20230826152706061

JWT是如何将原始的JSON格式数据,转变为字符串的呢? 其实在生成JWT令牌时,会对JSON格式的数据进行一次编码:进行base64编码 Base64:是一种基于64个可打印的字符来表示二进制数据的编码方式。既然能编码,那也就意味 着也能解码。所使用的64个字符分别是A到Z、a到z、 0- 9,一个加号,一个斜杠,加起来就是 64个字符。任何数据经过base64编码之后,最终就会通过这64个字符来表示。当然还有一个符 号,那就是等号。等号它是一个补位的符号 需要注意的是Base64是编码方式,而不是加密方式。

既然这样, 编码和加密的区别是什么呢?

加密是对数据进行安全编码的过程,以便只有知道密钥或密码的授权用户才能为其他人检索原始数据,这只是垃圾。 编码是将数据转换为这样一种格式的过程,该格式可以由不同类型的系统使用公开可用的算法进行。 加密的目的是转换数据以使其对他人保密。 编码主要目的是保护数据的完整性。

应用场景

JWT令牌最典型的应用场景就是登录认证:

  • 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成 一个jwt令牌,将生成的 jwt令牌返回给前端。
  • 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服 务端。
  • 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接 拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处 理。

在JWT登录认证的场景中我们发现,整个流程当中涉及到两步操作:

  1. 在登录成功之后,要生成令牌。
  2. 每一次请求当中,要接收令牌并对令牌进行校验。

生成和校验

首先需要映入JWT的依赖

<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

生成JWT代码实现

@Test
public void genJwt(){
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","Tom");
String jwt = Jwts.builder()
 .setClaims(claims) //自定义内容(载荷)
 .signWith(SignatureAlgorithm.HS256, "itheima") //签名算法
 .setExpiration(new Date(System.currentTimeMillis() +
24*3600*1000)) //有效期
 .compact();//使其返回一个对象
System.out.println(jwt);
}

运行测试方法:

eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMwfQ.fHi0Ub8npbyt71
UqLXDdLyipptLgxBUg_mSuGJtXtBk

输出的结果就是生成的JWT令牌,,通过英文的点分割对三个部分进行分割,我们可以将生成的令牌复制 一下,然后打开JWT的官网,将生成的令牌直接放在Encoded位置,此时就会自动的将令牌解析出来。

image-20230826153437066

第一部分解析出来,看到JSON格式的原始数据,所使用的签名算法为HS256。 第二个部分是我们自定义的数据,之前我们自定义的数据就是id,还有一个exp代表的是我们所设 置的过期时间。 由于前两个部分是base64编码,所以是可以直接解码出来。但最后一个部分并不是base64编 码,是经过签名算法计算出来的,所以最后一个部分是不会解析的。

校验JWT令牌(解析生成的令牌):

@Test
public void parseJwt(){
Claims claims = Jwts.parser()
 .setSigningKey("itheima")//指定签名密钥(必须保证和生成令牌时使用
相同的签名密钥)

.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMw
fQ.fHi0Ub8npbyt71UqLXDdLyipptLgxBUg_mSuGJtXtBk")
 .getBody();
System.out.println(claims);
}

(以上参考了黑马程序员B站教程)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落雨既然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值