JWT深入浅出

文章目录

  • JWT深入浅出
    • 1.JWT是什么
    • 2.为什么选JWT
      • 2.1 传统Session认证
      • 2.2 JWT认证
    • 3.JWT怎么用
    • 4. jwt绝对安全吗?

JWT深入浅出

1.JWT是什么

JWT(JSON Web Token)是一种用于在网络应用间传递信息的开放标准,通常用于身份认证和非敏感数据的传递(签名技术是保证传输的信息不被篡改,并不能保证信息传输的安全

JWT以点分隔的三部分组成:Header头部,Payload载荷,Signature签名

JWT举例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

我们可以直接通过官网(https://jwt.io/#debugger-io)解析出JWT三部分表示的内容

  • Header头部:通常包含Token类型(即JWT)和使用的签名加密算法,用JSON格式表示,将JOSN对象用base64编码得到JWT的Header部分(不是加密,是编码!)
  • Payload有效载荷:携带数据。是一个包含了声明 (claims) 的 JSON 对象,用于描述关于 JWT 的信息。
  • Signature签名:JWT 的签名通常是通过使用密钥和指定的加密算法对头部和负载进行签名生成的。密钥存储在服务器端,JWT的签发生成就是在服务器端完成。注意:服务器JWT 的签名部分用于验证 JWT 的完整性和真实性。

验证 JWT 时,接收方会使用相同的密钥和算法,对接收到的头部和负载进行签名计算,并与 JWT 中的签名部分进行比较。如果两者一致,则说明 JWT 是合法的,且未被篡改;否则,JWT 将被视为不可信任或无效。

签名部分的存在使得 JWT 在传输过程中具有完整性和真实性保护,但是需要确保密钥的安全性,因为持有正确密钥的任何人都能够验证 JWT 的真实性。

下面扩展对称加密和非对称加密:

  • 对称加密:对称加密使用相同的密钥来加密和解密数据。这意味着发送方和接收方都必须共享同一个密钥
  • 非对称加密:非对称加密使用一对密钥,分为公钥和私钥。公钥用于加密数据,私钥用于解密数据

2.为什么选JWT

常用于用户认证

2.1 传统Session认证

用户通过用户名密码进行身份验证,服务器端验证用户提供的凭据是否正确并确定用户是否有权限访问该资源。

如果用户提供凭据有效,服务器会创建并维护一个会话Session,记录用户相关的身份权限信息,并响应用户一个包含会话标识符session IDCookie。客户端cookie存储在本地,并在后续每次请求携带cookie(包含session ID)。服务器会通过session ID来识别用户

image-20240420113820653

暴露的问题:

  • 随着用户激增,服务器端在内存中维护的session开销也会很大,服务器增加负担(JWT就只需要根据签名加密算法和密钥验证JWT即可,无需繁琐操作)
  • 由于session是存在与服务器的物理内存中。在分布式的应用上,存在相同资源的多个服务器,难道每个服务器都登录授权?这大大限制了负载均衡器的能力。以此限制了分布式应用的扩展能力,不方便集群应用。(JWT就只需要根据签名加密算法和密钥验证JWT即可,无需繁琐操作)虽然可以将session统一保存到Redis中,但是这样做无疑增加了系统的复杂性,对于不需要redis的应用也会白白多引入一个缓存中间件
  • 因为session认证本质基于cookie,所以如果cookie被截获,用户很容易收到跨站请求伪造攻击。并且如果浏览器禁用了cookie,这种方式也会失效
  • 前后端分离系统中更加不适用,后端部署复杂,前端发送的请求往往经过多个中间件到达后端,cookie中关于session的信息会转发多次
  • 由于基于Cookie,而cookie无法跨域,所以session的认证也无法跨域,对单点登录不适用(单点登录是一种身份认证和授权机制,它允许用户使用同一套认证信息(如用户名和密码)来访问多个相关的、但又是相互独立的软件应用系统)

2.2 JWT认证

用户通过用户名密码进行身份验证,服务器端核对用户名密码后,生成JWT返回前端,前端本地存储JWT(推出登录删除JWT即可),并在后续的请求中携带JWT,服务器处理请求时只需要验证JWT的合法性即可(即通过密钥和签名加密算法对Header和payload部分进行加密,若与签名部分相等即为合法)

image-20240420115750584

JWT优点:

  • 不需要在服务端保存会话信息,特别适用于分布式微服务
  • Token是以JSON加密的形式保存在客户端,所以JWT是跨语言的,原则上任何web形式都支持
  • 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
  • 单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是使用token进行认证及没有这样的问题

3.JWT怎么用

添加依赖

<dependencies><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency>
</dependencies>

添加工具类:

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;
import java.util.Date;public class JwtHelper {//指定jwt过期时间private static long tokenExpiration = 365*24*60*60*1000;//指定jwt的签名密钥private static String tokenSignKey = "lpyx";//根据usesrId和userName创建JWT并返回public static String createToken(Long userId, String userName) {String token = Jwts.builder().setSubject("lpyx-USER").setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)).claim("userId", userId).claim("userName", userName).signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();return token;}//通过jwt返回用户idpublic static Long getUserId(String token) {if(StringUtils.isEmpty(token)) return null;Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();Integer userId = (Integer)claims.get("userId");return userId.longValue();}public static String getUserName(String token) {if(StringUtils.isEmpty(token)) return "";Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();return (String)claims.get("userName");}public static void removeToken(String token) {//jwttoken无需删除,客户端扔掉即可。}public static void main(String[] args) {String token = JwtHelper.createToken(7L, "admin");System.out.println(token);System.out.println(JwtHelper.getUserId(token));System.out.println(JwtHelper.getUserName(token));}
}

4. jwt绝对安全吗?

为了防止JWT被挟持和恶意攻击,可以采取以下措施:

  1. 使用HTTPS:确保JWT在传输过程中使用HTTPS协议进行加密传输,以防止中间人攻击。
  2. 设置合适的过期时间:为JWT设置较短的过期时间,以减少JWT被挟持后的风险。
  3. 存储敏感信息在服务器端:不要在JWT中存储敏感信息,如密码、密钥等。这些信息应该存储在服务器端的安全存储中。
  4. 验证JWT的完整性:在服务器端验证JWT的签名和负载内容,确保JWT没有被篡改或伪造。
  5. 防止CSRF攻击:使用CSRF令牌、验证请求来源等方法来防止CSRF攻击。
  6. 限制JWT的使用范围:为JWT设置适当的使用范围(audience),确保JWT只能在指定的应用程序或服务中使用。

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

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

相关文章

Unity VR在编辑器下开启Quest3透视(PassThrough)功能

现在有个需求是PC端串流在某些特定时候需要开启透视。我研究了两天发现一些坑,记录一下方便查阅,也给没踩坑的朋友一些思路方案。 先说结论,如果要打PC端或者在Unity编辑器中开启,那么OpenXR当前是不行的可能还需要一个长期的过程,必须需要切换到Oculus。当然Unity官方指…

机器人系统可以支持对接人工系统吗?

​ 随着科技的飞速发展&#xff0c;机器人系统在各行各业都扮演着越来越重要的角色。它们可以高效地处理大量数据&#xff0c;执行繁琐的任务&#xff0c;甚至在某些领域超越了人类的能力。然而&#xff0c;机器人系统也有其局限性&#xff0c;特别是在处理复杂的人际交往…

机器学习作业4——朴素贝叶斯分类器

目录 一、理论 一个例子&#xff1a; 二、代码 对于代码的解释&#xff1a; 1.fit函数&#xff1a; 2.predict函数: 三、实验结果 原因分析&#xff1a; 一、理论 朴素贝叶斯分类器基于贝叶斯定理进行分类&#xff0c;通过后验概率来判断将新数据归为哪一类。通过利用贝…

SpringCloud面试题

SpringCloud常见组件有哪些 注册中心组件&#xff1a;Eureka、Nacos 负载均衡组件&#xff1a;Ribbon 远程调用组件&#xff1a;OpenFeign 网关组件&#xff1a;Zuul、Gateway 服务保护组件&#xff1a;Hystrix、Sentinel 服务配置管理组件&#xff1a;SpringCloudConfig、Nac…

Qt跨平台开发demo(适用萌新)

最近需要参与一款Qt跨平台的软件开发&#xff0c;在此之前&#xff0c;特把基础信息做学习和梳理&#xff0c;仅供参考。 所使用的技术和版本情况如下&#xff1a; 虚拟机&#xff1a;VMware 16.2.5操作系统&#xff1a;ubuntu-20.04.6-desktop-amd64&#xff1a;Mysql数据库…

纯血鸿蒙APP实战开发——数字滚动动效实现

介绍 本示例主要介绍了数字滚动动效的实现方案。 该方案多用于数字刷新&#xff0c;例如页面刷新抢票数量等场景。 效果图预览 使用说明&#xff1a; 下拉页面刷新&#xff0c;数字进行刷新。 实现思路 通过双重ForEach循环分别横向、纵向渲染数字。 Row() {ForEach(this…

服装店会员管理系统结合小程序商城帮你挖掘出潜在客户

在现代社会&#xff0c;随着科技的不断进步和人们消费习惯的变化&#xff0c;传统的服装店已经不再能够满足消费者的需求。为了更好地服务客户&#xff0c;提升销售业绩&#xff0c;许多服装店开始引入会员管理系统&#xff0c;并结合小程序商城&#xff0c;实现线上线下的无缝…

AJAX前端与后端交互技术知识点以及案例

Promise promise对象用于表示一个异步操作的最终完成&#xff08;或失败&#xff09;及其结果值 好处&#xff1a; 逻辑更清晰了解axios函数内部运作机制成功和失败状态&#xff0c;可以关联对应处理程序能解决回调函数地狱问题 /*** 目标&#xff1a;使用Promise管理异步任…

C++ int 学习

在C语言中 & 是取地址符号&#xff1b; 在C中有 int& 这样的&#xff0c;这里的&不是取地址符号&#xff0c;而是引用符号&#xff1b; 引用是C对C的一个补充&#xff1b; 变量的引用就是变量的别名&#xff0c;讲的通俗一点就是另外一个名字&#xff1b; a的值…

鸿蒙开发接口Ability框架:【(AbilityContext)】

AbilityContext AbilityContext是Ability的上下文环境&#xff0c;继承自Context。 AbilityContext模块提供允许访问特定于ability的资源的能力&#xff0c;包括对Ability的启动、停止的设置、获取caller通信接口、拉起弹窗请求用户授权等。 说明&#xff1a; 本模块首批接口…

040——移植数据库sqlite3到i.mx6ull

目录 一、下载 二、移植数据库 三、测试sqlite3 一、下载 SQLite Download Page 暂时先下载最新版的试试&#xff0c;我们以前其实在ubuntu上直接使用过 嵌入式数据库sqlite3_常见的嵌入式数据库-CSDN博客 当时我把常用的操作和怎么使用记录下来了 现在把他移植到开发板…

Android11 InputManagerService启动流程分析

InputManagerService在systemserver进程中被启动 //frameworks\base\services\java\com\android\server\SystemServer.java t.traceBegin("StartInputManagerService"); inputManager new InputManagerService(context);//1 t.traceEnd(); //省略 //注册服务 Servi…

C++11:常用语法汇总

目录 &#x1f341;统一的列表初始化 { }initializer_list &#x1f341;decltype 推导表达式类型&#x1f341;可变参数模板解析可变参数包方法一方法二 &#x1f341;lambda 表达式捕捉列表的使用运用场景举例lambda表达式 与 函数对象 &#x1f341;统一的列表初始化 { } 在…

2024最新商业视频打赏系统源码 多套模板 有代理后台 已对接支付

简介&#xff1a; 2024最新商业视频打赏系统源码 多套模板 有代理后台 已对接支付 图片&#xff1a; 源码下载

【Python从入门到进阶】54、使用Python轻松操作SQLite数据库

一、引言 1、什么是SQLite SQLite的起源可以追溯到2000年&#xff0c;由D. Richard Hipp&#xff08;理查德希普&#xff09;所创建。作为一个独立的开发者&#xff0c;Hipp在寻找一个能够在嵌入式系统中使用的轻量级数据库时&#xff0c;发现现有的解决方案要么过于庞大&…

并发-守护线程setDaemon()

目录 为什么存在 什么是守护线程 创建守护线程 在使用守护线程时需要注意以下几点 可以使用isDaemon()方法来检查线程是否是守护线程 例1&#xff1a;上面提到当JVM中只剩下守护线程的时候&#xff0c;JVM就会退出&#xff0c;那么写段代码测试下 例2&#xff1a;thread…

练习队列的相关操作:循环队列

1. 思路解析 循环队列就是在只有有限的空间时使用队列实现循环存储数据&#xff0c;有双向链表和数组两种选择&#xff0c;这里我们使用数组实现循环队列&#xff08;因为链表我不会 >-<&#xff09; 2. 相关函数及其实现 2.1 判空与判满 判空&#xff1a;直接返回头尾…

docker(四):数据卷

数据卷 卷的设计目的就是数据的持久化&#xff0c;完全独立于容器的生存周期&#xff0c;因此Docker不会在容器删除时删除其挂载的数据卷。 1、docker run docker run -it --privilegedtrue -v /宿主机绝对路径目录:/容器内目录 镜像名2、挂载注意事项 --privilegedtru…

【C++】二叉搜索树(手撕插入、删除、寻找)

一、什么是二叉搜索树 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左…

OSError: [WinError 1455] 页面文件太小,无法完成操作 的问题

实质问题是报错&#xff1a;caffe2_detectron_ops.dll“ or one of its dependencies 还需要安装一个包&#xff1a; pip install intel-openmp 安装之后顺利测试通过。