JWT - 令牌认证授权(认证流程、认证原理、Jwt 工具类)

目录

一、JWT 认证

1.1、对 JWT 的认识

1.1.1、JWT 解释

1.1.2、为什么使用的 JWT 认证,而不是 Session 认证?

a)基于传统的 Session 认证

1.1.3、JWT 认证流程

1.1.4、优势

1.1.5、JWT 的结构

JWT 第一部分:标头 Header

JWT 第二部分:有效载荷 Payload 

JWT 第三部分:签名 Signature

1.2、JWT 的使用

1.2.1、实例

a)引入 jwt 依赖

b)生成 Token

c)根据密钥创建验证对象,然后验证 Token

d)执行结果

1.2.2、封装 Jwt 工具类


一、JWT 认证


1.1、对 JWT 的认识

1.1.1、JWT 解释

JWT 是 “JSON Web Token” 的简写,也就是通过 JSON 形式作为 Web 应用中的令牌,用于在各方之间安全的将信息作为 JSON 对象传输.  在数据传输过程中还可以完成数据加密,签名等相关处理.

这就像是皇上的玉玺,谁见到了哪怕没见过皇上长啥样,都知道是皇上来了.

1.1.2、为什么使用的 JWT 认证,而不是 Session 认证?

a)基于传统的 Session 认证

http 协议是一种无状态的协议,也就意味着当用户第一次通过用户名和密码登录成功以后,下一次再请求的时候,用户还需要再进行登录才行,因为根据 http 协议,我们不能知道是哪个用户发出的请求. 

为了解决上述问题,就是引入了 session 认证机制.  用户第一次登录成功之后,服务端会生成一个 sessionId,将他保存到内存中,然后加入到响应中(set-cookie)发送给客户端,接着客户端保存到本地,之后客户端每次访问服务器时都会带上这个 sessionId 作为身份标识,服务端也就知道这个请求是来自于哪个用户了.

弊端:

1. 占用大量服务器内存:每个用户经过认证之后都会再服务器的内存中记录一次,随着用户的增多,服务端的内存开销会明显增加.

2. 限制分布式架构的应用:用户认证之后会将 sessionId 保存到内存中,这就意味着用户下次请求必须要请求到这台服务器上,才完成能授权.  在分布式系统中,一定程度上增大了配置 负载均衡 的复杂度(指定请求打到记录 sessionId 的不同服务器).

3. 如果后端需要实现 session 共享机制,还需要进行 redis 集群的部署,加大了部署难度. 

4. 因为是基于 cookie 来进行用户识别的(set-cookie),cookie 如果被捕获,用户很容易受到 CSRF(跨网站请求伪造的攻击).

1.1.3、JWT 认证流程

1. 首先前端将用户名和密码发送给后端,后端对用户名和密码校验成功后,会将用户 id 和其他信息作为 payload ,然后将其分别进行 Base64 编码,拼接,最后再签名,形成一个 JWT(Token).  形成的 JWT 就形同 xxx.yyy.zzz 这种结构的字符串.

2. 后端将 JWT 字符串作为登录成功的响应结构返回给前端.  前端就可以通过 localStorage 保存到本地.  用户退出登录时删除保存的 JWT 即可.

3. 之后前端每次请求都会将 JWT 放入 HTTP Header 中的 Authorization 位(解决 XSS 和 XSRF 问题).

4. 之后后端每次收到请求后都会先验证 JWT 的有效性.  例如,检查签名是否正确、Token 是否过期、Token 的接收方是否是自己(可选).

1.1.4、优势
  1. 简洁:通过 POST 请求在 Header 中传参,数据量小,传输速度快.
  2. 自包含:负载中包含了所有用户所需要的信息,避免了多次查询数据库.
  3. 支持多种语言:Token 时以 JSON 加密的形式保存在客户端的. 原则上任何 web 都支持.
  4. 适用于分布式微服务,无需内存开销:不需要在服务端保存会话.
  5. 信息安全:由于签名是使用 标头 和 有效负载 计算的,因此还可以验证内容是否遭到篡改.

1.1.5、JWT 的结构

JWT 令牌由三个部分组成,分别是 标头(Header)、有效载荷(Payload)、签名(Signature),并且由 "." 分割.

类似于 xxxx.yyyy.zzzzz ,也就是 Header.Payload.Signature

JWT 第一部分:标头 Header

标头通常由两个部分组成,分别是 令牌的类型(例如 JWT) 和 所使用的签名算法.(例如HMAC、SHA256、RSA.  一般就是用 HS 256 即可).  

例如:

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

最后,他会使用 Base64 编码构造出 JWT 结构中的第一部分(Header).

Ps:Base64 只是一种编码,也就是说,可以被翻译回原来的样子. 因此他并不是一种加密过程.

JWT 第二部分:有效载荷 Payload 

令牌的第二部分就是有效载荷,这就是我们一些自定义传输的信息,通常是一些用户信息.

Ps:值得注意的是,Base64 是一种编码,可以被翻译回来,因此在 JWT 中不因该在 负载 中加入任何敏感数据,例如用户密码.

例如:

{"id": "6","username": "cyk","admin": true
}

最后,他会使用 Base64 编码构造出 JWT 结构中的第二部分(Payload).

JWT 第三部分:签名 Signature

Signatrue 需要使用 Base64 编码后的 header 和 payload 以及提供的 密钥(私钥),然后使用 header 中指定的签名算法(HS256)构建一个签名,保证 JWT 没有被篡改过.

例如,一旦篡改 header 中的信息,那么服务端拿到传来的 JWT,会先进行验签,就是拿着新的 JWT 的第一部分和第二部分,再以同样的 密钥(私钥) 再生成一个 JWT 第三部分(签名),然后拿着这个新生成的 签名和 前端刚刚传来的 JWT 的第三部分进行比对,就会对比出不一致.

Ps:这就使得后端不需要存储任何数据,就可以校验用户的身份,避免了使用 session 而导致占用大量内存空间.

1.2、JWT 的使用

1.2.1、实例

这里用一个简单的栗子来演示 JWT 的使用.

a)引入 jwt 依赖
        <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>
b)生成 Token
    @Testpublic void createJwt() {//设置令牌的过期时间位 100 sCalendar instance = Calendar.getInstance();instance.add(Calendar.SECOND, 100);//创建 TokenString token = JWT.create().withClaim("userId", 6) //payload.withClaim("username", "cyk") //payload.withExpiresAt(instance.getTime()) //设置过期时间.sign(Algorithm.HMAC256("djafo&*&(988*T*"));//签名(这里自定义密钥即可)System.out.println(token);}

执行之后,通过 sout 展示 token 如下:

c)根据密钥创建验证对象,然后验证 Token
    @Testpublic void test() {//创建验证对象JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("djafo&*&(988*T*")).build();//验证Token(验证失败,会引发异常)DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTcxNjcwNTMsInVzZXJJZCI6NiwidXNlcm5hbWUiOiJjeWsifQ.WsDPqbmeeqyKPMRllrDv4kfUL-m6hZxAfGc21-t51GE");System.out.println(verify.getClaim("userId").asInt());System.out.println(verify.getClaim("username").asString());}

一旦执行失败,则会引发如下异常:

  • SignatureVerificationException:签名不一致异常.
  • TokenExpiredException:令牌过期异常.
  • AlgorithmMismatchException:算法不匹配异常.
  • InvalidClaimException:失败的 payload 异常.

d)执行结果

1.2.2、封装 Jwt 工具类

未来在我们的项目中,肯定是需要对上述过程进行封装来使用的.

主要有三个方法:

  1. 生成 Token.
  2. 验证 Token 合法性.
  3. 获取 Token.
/*** Jwt 工具类*/
public class JwtUtils {//自定义密钥private static final String SIGN = "Y*(GY*G^&*%69g*()&";/*** 生成 Token* @param map 自定义的载荷数据* @return 返回 Token*/public static String createToken(Map<String, String> map) {//1.设置过期时间(默认 1 天过期)Calendar instance = Calendar.getInstance();instance.add(Calendar.DATE, 1);//2.创建 jwt builder,添加自定义的载荷数据JWTCreator.Builder builder = JWT.create();for(Map.Entry<String, String> entry : map.entrySet()) {builder.withClaim(entry.getKey(), entry.getValue());}//3.生成 TokenString token = builder.withExpiresAt(instance.getTime()) //过期时间.sign(Algorithm.HMAC256(SIGN));// signreturn token;}/*** 验证 Token 合法性* @param token*/public static void checkToken(String token) {JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);}/*** 获取 Token 信息* @param token* @return*/public static DecodedJWT getTokenInfo(String token) {DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);return verify;}}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode - 318 最大单词长度乘积(Java JS Py C)

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 318. 最大单词长度乘积 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个字符串数组 words &#xff0c;找出并返回 length(words[i]) * length(words[j]) 的最大值&#xff0c;并且这两个单词…

RocketMQ核心编程模型以及生产环境最佳实践

文章目录 一、深入理解RocketMQ的消息模型二、消息确认机制消息生产端采用消息确认加多次重试的机制保证消息正常发送到RocketMQ消息消费者端采用状态确认机制保证消费者一定能正常处理对应的消息消费者也可以自行指定起始消费位点 三、广播消息四、顺序消息机制五、延迟消息六…

【Mybatis】动态 SQL

动态 SQL \<if>标签\<trim>标签\<where>标签\<set>标签\<foreach>标签 动态 sql 是 Mybatis 的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接。 <if>标签 前端用户输入时有些选项是非必填的, 那么此时传到后端的参数是不确…

ipad手写笔哪个好用?苹果平替笔性价比高的

如果你想要入手一款和iPad匹配的电容笔&#xff0c;想必你的第一想法就是苹果的原装电容笔。然而这款电容笔虽然很好用&#xff0c;但价格会相对的昂贵一些。而平替电容笔&#xff0c;却是一种不错的选择&#xff0c;而且价格也很合理。一支普通的平板电容笔&#xff0c;其售价…

设计模式学习(十二)用设计模式干掉 if-else,太优雅了!

目录 一、场景举例二、什么时候需要改造 if-else&#xff1f;三、策略模式 Map字典3.1 策略接口3.2 策略实现类3.3 策略工厂类&#xff08;策略接口的持有者&#xff09;3.4 客户端&#xff08;测试类&#xff09;3.5 执行结果3.6 总结 四、责任链模式4.1 责任链处理接口4.2 责…

使用【Blob、Base64】两种方式显示【文本、图片、视频】 使用 video 组件播放视频

Blob 显示 Blob 对象的类型是由 MIME 类型&#xff08;Multipurpose Internet Mail Extensions&#xff09;来确定的。MIME 类型是一种标准&#xff0c;用于表示文档、图像、音频、视频等多媒体文件的类型。以下是一些常见的 Blob 对象类型&#xff1a; text/plain&#xff1…

2024届通信工程保研经验分享(预推免入营即offer)

2024届通信工程保研经验分享&#xff08;预推免入营即offer&#xff09; BackGround夏令营情况&#xff1a;预推免情况&#xff1a; BackGround 本科院校&#xff1a;末九 专业&#xff1a;通信工程 rank&#xff1a;3/123&#xff08;预推免绩点排名&#xff09;&#xff0…

基于行波理论的输电线路防雷保护

摘要 随着科技的发展&#xff0c;电力已成为最重要的资源之一&#xff0c;如何保证电力的供应对于国民经济发展和人民生活水平的提高都有非常重要的意义。输电线路的防雷保护就是重点之一。架空输电线路分布很广&#xff0c;地处旷野&#xff0c;易遗受雷击&#xff0c;线路的雷…

Apache Ranger:(二)对Hive集成简单使用

1.Ranger Hive-plugin安装 进入 Ranger 编译生成的目录下 找到 ranger-2.0.0-hive-plugin.tar.gz 进行解压 tar -zxvf ranger-2.0.0-hive-plugin.tar.gz -C /opt/module/ 2.修改配置文件 vim install.properties #策略管理器的url地址 POLICY_MGR_URLhttp://[ip]:6080#组件…

Ubuntu 22.04.3 LTS单机私有化部署sealos

推荐使用奇数台 Master 节点和若干 Node 节点操作系统 :Ubuntu 22.04 LTS内核版本 :5.4 及以上配置推荐 :CPU 4 核 , 内存 8GB, 存储空间 100GB 以上最小配置 :CPU 2 核 , 内存 4GB, 存储空间 60GB 这里采用的Ubuntu 22.04.3 LTS 版本&#xff0c;Ubuntu 20.04.4 LTS这个版本…

铅华洗尽,粉黛不施,人工智能AI基于ProPainter技术去除图片以及视频水印(Python3.10)

视频以及图片修复技术是一项具有挑战性的AI视觉任务&#xff0c;它涉及在视频或者图片序列中填补缺失或损坏的区域&#xff0c;同时保持空间和时间的连贯性。该技术在视频补全、对象移除、视频恢复等领域有广泛应用。近年来&#xff0c;两种突出的方案在视频修复中崭露头角&…

【案例讲解】LVGL关于旋转的配置

更多源码分析请访问:LVGL 源码分析大全 目录 1、前言2、问题原因3、修改方案3.1 直接修改代码3.2 修改配置3.3 降低 LV_DISP_ROT_MAX_BUF 值1、前言 在实现项目中,因为横竖屏的关系,需要对其做90度的旋转。配置旋转时发现一些局部刷新控件,旋转后效果不对。 异常图标正常…

finalshell连接虚拟机中的ubuntu

finalshell下载地址: https://www.finalshell.org/ubuntu设置root密码&#xff1a; sudo passwd rootubuntu关闭防火墙&#xff1a; sudo ufw disable安装ssh # sudo apt update #更新数据(可以不执行) # sudo apt upgrade #更新软件(可以不执行) sudo apt install open…

ACDSee Photo Studio Ultimate 2024特别版(图片编辑器)

ACDSee Photo Studio Ultimate 2024是一款功能全面、易于使用的图像编辑和管理软件&#xff0c;为摄影师和设计师提供了强大的工具和功能。无论您是进行基本的图像优化还是进行复杂的创作&#xff0c;ACDSee Photo Studio Ultimate 2024都将成为您的得力助手。 软件下载&#x…

HTML5的新增表单元素

HTML5 有以下新的表单元素: <datalist> <keygen> <output> datalist datalist 元素规定输入域的选项列表。 datalist属性规定 form 或 input 域应该拥有自动完成功能。当用户在自动完成域中开始输入时&#xff0c;浏览器应该在该域中显示填写的选项&…

Python3无法调用Sqlalchemy解决(mysqldb)

原因 在安装Sqlalchemy后运行程序报错 无法导入mysqldb&#xff0c;缺失模块 ImportError: No module named ‘MySQLdb’ 既然缺少 MySQLdb 这个模块&#xff0c;尝试按照正常的想法执行 pip install MySQLdbpip install mysql-python 应该能解决&#xff0c;但是却找不到…

再谈Java泛型

一.类型参数的约束 我们可以对泛型传进来的参数做一些约束&#xff0c;比如说 用extends表明传进来的参数类型必须是必须是某个类型的子类型或者本身 当然也可以用接口约束&#xff0c;也是用extends表明传进来的参数类型必须实现某个接口。用&连接&#xff0c;注意class…

基于springboot实现校园闲置物品交易平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现校园闲置物品交易平台系统演示 摘要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的交易方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&am…

和鲸 ModelWhale 与华为 OceanStor 2910 计算型存储完成兼容性测试

数智化时代&#xff0c;数据总量的爆炸性增长伴随着人工智能、云计算等技术的发展&#xff0c;加速催化了公众对于数据存储与应用的多元化需求。同时&#xff0c;数据也是重要的基础资源和战略资源&#xff0c;需要严格保障其安全性、完整性。搭建国产数据基础设施底座&#xf…

13.SpringBoot项目之Service层

SpringBoot项目之Service层 JavaEE三层架构 为了项目维护方便&#xff0c;为了项目开发便利。三层架构功能控制器层&#xff1a;controller方便和前端数据进行交互业务层&#xff1a;service处理各种业务持久化层&#xff1a;mapper和数据库进行数据交互 抽取出service层 按…