JWT深入浅出

news2024/11/18 12:47:07

文章目录

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

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

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

相关文章

LagentAgentLego智能体工具使用

1. lagent 参考文档 https://github.com/InternLM/Tutorial/blob/camp2/agent/lagent.md 使用 LMDeploy 部署 conda activate agent lmdeploy serve api_server /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-7b \--server-name 127.0.0.1 \--model-name in…

WebSocket前后端建立以及使用

1、什么是WebSocket WebSocket 是一种在 Web 应用程序中实现双向通信的协议。它提供了一种持久化的连接&#xff0c;允许服务器主动向客户端推送数据&#xff0c;同时也允许客户端向服务器发送数据&#xff0c;实现了实时的双向通信。 这部分直接说你可能听不懂&#xff1b;我…

线路和绕组中的波过程(三)

本篇为本科课程《高电压工程基础》的笔记。 本篇为这一单元的第三篇笔记。上一篇传送门。 冲击电晕对线路上波过程的影响 实际中的导线存在电阻&#xff0c;而且还有对地电导&#xff0c;会消耗一部分能量。但是因为雷击所涉及的传输距离很短&#xff0c;所以几乎可以忽略这…

acer笔记本怎样进行系统还原?教你两招!

acer笔记本怎样进行系统还原&#xff1f;教你两招&#xff01; 作为笔记本用户&#xff0c;你在日常使用中可能会遇到各种各样的电脑问题。一般来说&#xff0c;对于一些小问题&#xff0c;我们可以通过一些简单的操作来解决&#xff0c;比如重新启动电脑或者长按电源键强制关机…

【吴恩达机器学习-week2】多个变量的线性回归问题

文章目录 1.1 目标2 问题陈述2.1 包含我们示例的矩阵 X2.2 参数向量 w \mathbf{w} w 和 b b b 3 使用多个变量进行模型预测3.1 逐元素单独预测3.2 单一预测&#xff0c;向量 4 使用多个变量计算成本5 使用多个变量的梯度下降5.1 使用多个变量计算梯度 多个变量的梯度下降小结…

卷积特征图与感受野

特征图尺寸和感受野是卷积神经网络中非常重要的两个概念&#xff0c;今天来看一下&#xff0c;如何计算特征尺寸和感受野。 特征图尺寸 卷积特征图&#xff0c;是图片经过卷积核处理之后的尺寸。计算输出特征的尺寸&#xff0c;需要给出卷积核的相关参数包括&#xff1a; 输…

虚表,虚函数习题

6. 关于虚表说法正确的是&#xff08;d &#xff09; A&#xff1a;一个类只能有一张虚表 多重继承 B&#xff1a;基类中有虚函数&#xff0c;如果子类中没有重写基类的虚函数&#xff0c;此时子类与基类共用同一张虚表 即使子类重写了基类的虚函数&#xff0c;此时子类与…

模拟集成电路(3)----单级放大器(共源极)

模拟集成电路(3)----单级放大器&#xff08;共源极&#xff09; 放大是模拟电路的基本功能 大多数自然模拟信号太小而无法处理需要足够的信噪比 理想的放大器 线性&#xff1a;无限的幅度和频率范围 输入阻抗无限大 输出阻抗无限小 共源放大器 共源放大器就是将源极接A…

视频监控系统中,中心录像服务器的录像文件实际大小和理论值相差很大的问题解决

目录 一、现象描述 二、视频监控的录像文件计算 &#xff08;一&#xff09;计算方法 1、仅视频部分 2、视频和音频部分 3、使用平均码率 &#xff08;二&#xff09;计算工具 1、关注威迪斯特公众号 2、打开“计算容量”的小工具 三、原因分析 &#xff08;一&…

企业网络需求及适合的解决方案

近年来&#xff0c;企业网络通信需求可谓五花八门&#xff0c;变幻莫测。它不仅为企业的生产、办公、研发、销售提供全面赋能&#xff0c;同时也让企业业务规模变大成为了可能。 在当前的技术格局下&#xff0c;中大型企业常见的技术方案有很多&#xff0c;而同时也有各自不可替…

超级好看的html网站维护源码

源码介绍 好看的html网站维护源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c; 源码截图 源码下载 好看的html网站维护源码

【力扣】LCR 166.珠宝的最高价值

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 目录 1.题目描述 2.思路分析 3.代码实现 1.题目描述 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝…

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…

按键配合LDO实现开关功能

今天给大家分享一个学到的按键开关电路&#xff0c;适合没有足够空间给自锁开关的场景&#xff0c;既可以用于USB供电控制也可以用于电池供电控制。话不多说上电路图先。 核心任务就是通过按键控制LDO芯片的使能管脚的电平状态&#xff0c;这枚NCP芯片高电平使能&#xff0c;VB…

基于Nios软件实现流水灯+串口输出

基于NIOS-II软核实现流水灯串口输出 引言&#xff1a; ​ 在现代电子设计领域&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;因其灵活性和并行处理能力而成为实现复杂数字系统的首选平台。Nios II&#xff0c;作为Altera&#xff08;现为Intel旗下&#xff09;提供…

2016-2021年全国范围的2.5m分辨率的建筑屋顶数据

一、论文介绍 摘要&#xff1a;大规模且多年的建筑屋顶面积&#xff08;BRA&#xff09;地图对于解决政策决策和可持续发展至关重要。此外&#xff0c;作为人类活动的细粒度指标&#xff0c;BRA可以为城市规划和能源模型提供帮助&#xff0c;为人类福祉带来好处。然而&#xf…

WordPress原创插件:超链接点击访问统计

WordPress原创插件&#xff1a;超链接点击访问统计 https://download.csdn.net/download/huayula/89296775

ICode国际青少年编程竞赛- Python-4级训练场-while语句综合

ICode国际青少年编程竞赛- Python-4级训练场-while语句综合 1、 for i in range(4):while not Flyer[i].disappear():wait()Spaceship.step(6)Spaceship.turnLeft()2、 Dev.turnLeft() for i in range(4):Spaceship.step(2)while Flyer[i].disappear():wait()Dev.step(4)Dev.…

Go实现树莓派读取at24c02 eeprom读写数据

步骤 启用i2c 参考 Go实现树莓派读取bh1750光照强度 代码 package mainimport ("fmt""periph.io/x/conn/v3/i2c" )type AT24C02Device struct {dev *i2c.Dev }func NewAT24C02Device(addr uint16, bus i2c.BusCloser) (*AT24C02Device, error) {var (d…

【HDFS】关于HDFS-17497:在commit block时更新quota

链接:https://github.com/apache/hadoop/pull/6765 Ticket标题:The number of bytes of the last committed block should be calculated into the file length。 HDFS里,一个在写入的文件可能包含多个commited状态的块。 但是计算文件大小的时候,最后一个commited block并…