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返回用户id
    public 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只能在指定的应用程序或服务中使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

24寸2K显示器 - HKC G24H2

&#x1f525;&#x1f5a5;️ 嘿&#xff0c;大家好&#xff01;今天&#xff0c;我要给大家介绍一款超棒的显示器——HKCG24H2&#xff01;这款显示器可是个全能选手&#xff0c;无论你是工作狂人还是游戏迷&#xff0c;它都能满足你的需求&#xff01; &#x1f60e;&#x…

传输层之 UDP 协议

UDP协议端格式 教科书上的&#xff1a; 16位UDP长度&#xff0c;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的最大长度&#xff0c;描述了这个数据报多长&#xff1b; 实际上的&#xff1a; UDP 会把载荷数据&#xff0c;就是通过 UDP Socket&#xff0c;即 sen…

PyQt5批量生成Checkbox及批量检查Checkbox的勾选状态

批量生成Checkbox并添加到TableWidget中 for i in range(10):checkbox_i QCheckBox(fCheckbox_{i}) # 生成Checkbox并命名为Checkbox_iself.ui_1.tableWidget_1.setCellWidget(i,1,checkbox_i) 批量检查勾选状态 # 批量生成Checkbox并存入列表 list_Checkbox_1 [] for …

vue3专栏项目 -- 三、使用vue-router 和 vuex(下)

一、添加columnDetail 页面 首页有专栏列表&#xff08;ColumnList组件&#xff09;&#xff0c;专栏列表中有很多专栏&#xff0c;然后点击某个专栏就进入专栏详情页&#xff08;ColumnDetail组件&#xff09;&#xff0c;专栏详情页中有很多文章&#xff0c;点击某个文章就进…

uni-segmented-control插件使用

dcloud插件市场 前端/uniapp 1.HBuildX打开目标项目 2.进入dcloud插件市场下载目标插件 3.看到如下提示(已经可以在目标项目中使用插件啦) 4.项目正式使用

物联网平台之单体架构

介绍本文主要介绍平台的单体架构&#xff0c;包括各个组件之间的数据流描述以及所做的一些架构选择。在单体架构模式下&#xff0c;所有 ThingsKit 组件都在单个 Java 虚拟机 (JVM) 中启动&#xff0c;并共享相同的操作系统资源。由于 ThingsKit 是用 Java 编写的&#xff0c;因…

springcloud alibaba微服务框架涉及的技术

一、微服务架构中核心模块及其使用技术总览 二、各模块详细说明 1、注册中心 该模块主要功能为 自动提供服务的注册与发现&#xff0c;集中式管理服务&#xff0c;让 服务调用端发现服务&#xff0c;让服务提供端注册服务&#xff0c;倘若没有注册中心&#xff0c;那客户端就…

JUC下的BlockingQueue详解

BlockingQueue是Java并发包(java.util.concurrent)中提供的一个接口&#xff0c;它扩展了Queue接口&#xff0c;增加了阻塞功能。这意味着当队列满时尝试入队操作&#xff0c;或者队列空时尝试出队操作&#xff0c;线程会进入等待状态&#xff0c;直到队列状态允许操作继续。这…

记录使用极空间NAS通过Docker部署小皮面板(PhpStydy)运行 八图片当面付支付宝接口 PHP项目的遭遇

事件的起因还得从我用八图片的图片加密支付跳转功能&#xff0c;实现打赏金额发案例源码下载链接挣个烟钱的事。八图片的支付接口是PHP web项目的。正好我有个极空间的NAS&#xff0c;搭建到NAS上省去了买主机的费用。 导读 八图片是什么&#xff1f;极空间NAS 部署 PHP网站安装…

eNSP中小型园区网络拓扑搭建(上)

→b站直通车&#xff0c;感谢大佬← →eNSP中小型园区网络拓扑搭建&#xff08;下&#xff09;← 不带配置命令的拓扑图已上传~ 项目背景&#xff1a; 某公司准备新建一张网络供企业办公使用。写字楼共3层&#xff0c;一层会客大厅、二层行政部及市场部、三层研发部。一层设…

探讨 vs2019 c++ 里函数指针与函数类型在使用上的语法区别

&#xff08;1&#xff09;咱们可以用 decltype &#xff08;&#xff09; 来判断函数的类型。但以这个类型定义有用的可指向已存在函数的变量&#xff0c;却行不通。测试如下&#xff1a; 如果把上面的注释去掉会报错&#xff1a; 所以函数类型只有语法意义。但在使用上没有函…

InputStream,OutputStream的用法以及相应的案例

1. 文件系统的操作&#xff1a;File类。 2. 文件内容的操作&#xff1a;Stream流。 字符流&#xff1a;IntputStream &#xff0c; OutputStream。 字节流&#xff1a;read &#xff0c; write。 InputStream&#xff0c;OutputStream InputStream和OutputStream都不能被实例…

论文笔记:DeepMove: Predicting Human Mobility with Attentional Recurrent Networks

WWW 2018 1 Intro 根据对百万级用户群的研究&#xff0c;93%的人类移动是可预测的。 早期的mobility预测方法大多基于模式的。 首先从轨迹中发现预定义的移动模式(顺序模式、周期模式)然后基于这些提取的模式预测未来位置。最近的发展转向基于模型的方法进行流动性预测。 利用…

Django性能之道:缓存应用与优化实战

title: Django性能之道&#xff1a;缓存应用与优化实战 date: 2024/5/11 18:34:22 updated: 2024/5/11 18:34:22 categories: 后端开发 tags: 缓存系统Redis优点Memcached优缺点Django缓存数据库优化性能监控安全实践 引言 在当今的互联网时代&#xff0c;用户对网站和应用…

阿里云Redis创建使用

说明&#xff1a;本文介绍如何使用阿里云Redis&#xff0c;包括开通、连接、使用&#xff1b; 开通 进入官网Redis产品页&#xff0c;点击免费试用&#xff08;白嫖&#xff09;&#xff1b; 选择中间这个&#xff0c;云数据库Redis版&#xff1b; 开通完成后&#xff0c;可在…

应对【核弹级风险】,中小企业如何构建【轻量级】开源治理策略?

开源 三句半 开源治理建团队 制度工具要完善 积极参与开源事 深度实践&#xff01; 4月份曝光的“XZ后门事件”是一起历时两年半的“开源供应链投毒”典型案例&#xff0c;被定义为“核弹级漏洞事件”&#xff0c;其揭示了开源技术的安全短板&#xff0c;引发了众多企业的紧急…

C++青少年简明教程:基础知识

C青少年简明教程&#xff1a;基础知识 电脑程序设计&#xff08;Computer programming&#xff09;&#xff0c;或称程序设计&#xff08;programming&#xff09;&#xff0c;是给出解决特定问题程序的过程&#xff0c;程序设计往往以某种程序设计语言为工具&#xff0c;给出这…

【Android】Kotlin学习之Kotlin方法的声明和传参

方法声明 普通类的方法 静态类的方法 不需要构建实例对象, 可以通过类名直接访问静态方法 : NumUtil.double(1) companion object 伴生类的方法 使用companion object 在普通类里定义静态方法 参数 括号内传入方法 : 当参数是方法时, 并且是最后一个参数 , 可以使用括号外…

关于DDD和COLA的一些总结和思考

1|0思维&#xff1a;面向对象和面向过程 领域驱动设计本质上是讲的面向对象&#xff0c;但是谈面向对象&#xff0c;始终无法绕开面向过程&#xff0c;所以我们先好好说一下面向过程和面向对象这两个概念。 什么是面向过程呢&#xff0c;其实就是我们学习编程时最初被植入的逻辑…

Redis 实战之事务的实现

事务的实现 事务开始命令入队事务队列执行事务总结 一个事务从开始到结束通常会经历以下三个阶段&#xff1a; 1、 事务开始&#xff1b; 2、 命令入队&#xff1b; 3、事务执行。 本节接下来的内容将对这三个阶段进行介绍&#xff0c; 说明一个事务从开始到结束的整个过程。 …