浅浅了解一下JWT

news2024/9/25 17:14:40

JWT 介绍

JWT 是 JSON Web Token 的缩写,JWT 本身没有定义任何技术实现,它只是定义了一种基于 Token 的会话管理的规则,涵盖 Token 需要包含的标准内容和 Token 的生成过程。

首先,俺们先来看看一个 JWT Token 长这样。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDQ1MTE3NDMsImp0aSI6IjYxYmVmNjkyLTE4M2ItNGYxYy1hZjE1LWUwMDM0MTczNzkxOSJ9.CZzB2-JI1oPRFxNMaoFz9-9cKGTYVXkOC2INMoEYNNA

仔细辨别会发现它由 A.B.C 三部分组成,这三部分依次是头部(Header)、负载(Payload)、签名(Signature),头部和负载以 JSON 形式存在,这就是 JWT 中的 JSON,三部分的内容都分别单独经过了 Base64 编码,以 . 拼接成一个 JWT Token。

  • 头部(Header)

    JWT 的 Header 中存储了所使用的加密算法和 Token 类型。

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • 负载(Payload)

    Payload 是负载,JWT 规范规定了一些字段,并推荐使用,开发者也可以自己指定字段和内容,例如下面的内容。

    {
      id: 1024
      username: 'admin',
      exp: 1544602234
    }
    

    需要注意的是,Payload的内容只经过了 Base64 编码,对客户端来说当于明文存储,所以不要放置敏感信息。

  • 签名(Signature)

    Signature 部分用来验证 JWT Token 是否被篡改,所以这部分会使用一个 Secret 将前两部分加密,逻辑如下。

    HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
    

JWT 优势 & 问题

思考一下:

为什么要用JWT?

互联网服务离不开用户认证,传统的认证方式是通过cookie和session的方式进行认证,但是分布式web应用的普及,通过session管理用户登录状态成本越来越高,你想想看,当业务服务分布在多台服务器时,该怎么进行session认证呢。

有人会说,每个业务服务都保持session同步不就好了,你细想,是不是要维护每台session,每台服务器都要读取 session,还有串session的风险,代价是不是很大。

有人还会说,像sso一样,所有请求先经过认证服务,session只在认证服务上保存不就好了。其实这种方式也为尝不可,只是每个用户都会产生一个session进行维护,客户端还需维护cookie,session量大起来了的话复杂度也随之提高了,session的存取都会占用服务器资源,用户量很大的情况下,会产生各种问题,性能比较低下。

优势

​ JWT 拥有基于 Token 的会话管理方式所拥有的一切优势,不依赖 Cookie,使得其可以防止 CSRF 攻击,也能在禁用 Cookie 的浏览器环境中正常运行。

问题

​ 而 JWT 的最大优势是服务端不再需要存储 Session,使得服务端认证鉴权业务可以方便扩展,避免存储 Session 所需要引入的 Redis 等组件,降低了系统架构复杂度。但这也是 JWT 最大的劣势,由于有效期存储在 Token 中,JWT Token 一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的 JWT Token,如果需要禁用用户,单纯使用 JWT 就无法做到了。

JWT 的几个特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

基于 JWT 的实践

既然 JWT 依然存在诸多问题,甚至无法满足一些业务上的需求,但是我们依然可以基于 JWT 在实践中进行一些改进,来形成一个折中的方案

Token续期

对于了解jwt的同学来说,jwt有个弊端,jwt不允许续签时间,时间到期,token就过期。以下实践方案也是续签的一直思路。

在 JWT 的实践中,引入 Refresh Token,将会话管理流程改进如下。

  • 客户端使用用户名密码进行认证
  • 服务端生成有效时间较短的 Access Token(例如 10 分钟),和有效时间较长的 Refresh Token(例如 7 天)
  • 客户端访问需要认证的接口时,携带 Access Token
  • 如果 Access Token 没有过期,服务端鉴权后返回给客户端需要的数据
  • 如果携带 Access Token 访问需要认证的接口时鉴权失败(例如返回 401 错误),则客户端使用 Refresh Token 向刷新接口申请新的 Access Token
  • 如果 Refresh Token 没有过期,服务端向客户端下发新的 Access Token(也可下发新的Refresh Token以达到未退出浏览器未关闭一直登录的状态)
  • 客户端使用新的 Access Token 访问需要认证的接口
  • 如果 Refresh Token 过期,则重新使用用户名密码进行认证

img

​ 将生成的 Refresh Token 以及过期时间存储在服务端的数据库中,由于 Refresh Token 不会在客户端请求业务接口时验证,只有在申请新的 Access Token 时才会验证,所以将 Refresh Token 存储在数据库中,不会对业务接口的响应时间造成影响,也不需要像 Session 一样一直保持在内存中以应对大量的请求。

​ 上述的架构,提供了服务端禁用用户 Token 的方式,当用户需要登出或禁用用户时,只需要将服务端的 Refresh Token 禁用或删除,用户就会在 Access Token 过期后,由于无法获取到新的 Access Token 而再也无法访问需要认证的接口。这样的方式虽然会有一定的窗口期(取决于 Access Token 的失效时间),但是结合用户登出时客户端删除 Access Token 的操作,基本上可以适应常规情况下对用户认证鉴权的精度要求。


我习惯的实现方式:

  1. 用户注册/登录时,服务端会分配给该用户一个token,有效期30天,入库后下发给客户端。

  2. 客户端可以将该token放在header里,也可以放在请求json中。放在cookie中自然也可以的,取决于具体业务场景和实现约定。

  3. 服务端的权限系统对用户鉴权,若鉴权通过则执行业务逻辑;否则提示用户重新登录。

    优点:

    • 同样不依赖Cookie。

    • 用户登录后会生成新token,老token自动失效。即只允许用户登录一个设备。

    • 服务端可以随时踢掉用户当前的登录状态,服务端只需要重置token即可。随后的客户端请求所携带的token都会被服务端判定失效,把客户端打回登录界面。

    • 用户登出,则只需要客户端删除存储的token即可,服务端不必理会。下次用户登录时,服务端自会重新给该用户分配一个新的token。

Java-Jwt实现案例

1、倒入依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

2、创建token

 		/**
     * 创建token
     * @param user
     * @return
     */
    public static String createToken(Users user){
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,TIME_OUT_DAY);
        String token = JWT.create()
                .withClaim("id", user.getId())
                .withClaim("key", DigestUtils.md5DigestAsHex(user.getPassword().getBytes()))
                .withExpiresAt(calendar.getTime())
                .sign(Algorithm.HMAC256(SECRET));
        return token;
    }

3、生成token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDQ1MTE3NDMsImp0aSI6IjYxYmVmNjkyLTE4M2ItNGYxYy1hZjE1LWUwMDM0MTczNzkxOSJ9.CZzB2-JI1oPRFxNMaoFz9-9cKGTYVXkOC2INMoEYNNA

4、校验token是否过期

 /**
     * 校验token是否过期
     * @param decodedJWT
     * @return
     */
    public static boolean needCreate(DecodedJWT decodedJWT){
        Date timeoutDate = decodedJWT.getExpiresAt();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,TIME_OUT_DAY - NEED_CREATE_DAY);
        if(timeoutDate.before(calendar.getTime())){
            return true;
        }
        return false;
    }

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

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

相关文章

burpsuite 插件编写入门

文章目录 一、什么是扩展 / 插件&#xff1f;实现一个简单的 插件/扩展 系统 二、burp 的扩展三、开发步骤总结 一、什么是扩展 / 插件&#xff1f; 关于这个话题&#xff0c;知乎有一个回答题不错&#xff0c;主要也是引用了wikipedia 插件/扩展&#xff0c;是向现有的计算机…

Go的Gin框架拦截器实现登录认证结合JWT实现会话记录

JWT jwt全称 Json web token&#xff0c;是一种认证和信息交流的工具。 授权&#xff1a;这是使用JWT最常见的场景。一旦用户登录&#xff0c;每个后续请求都将包含JWT&#xff0c;允许用户访问该令牌允许的路由、服务和资源。 信息交流&#xff1a;JSON Web令牌是在各方之间…

3.redis-事务

01-Redis事务概述 概述 Redis事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化放到一个队列中按顺序地执行。事务 在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 不支持ACID ①atomicity, 原子性, redis事务中的指令执行失败, 不影响后…

记一次 腾讯会议 的意外崩溃分析

一&#xff1a;背景 1. 讲故事 前段时间在用 腾讯会议 直播的时候&#xff0c;居然意外崩溃了&#xff0c;还好不是在训练营上课&#xff0c;不然又得重录了&#xff0c;崩完之后发现 腾讯会议 的 bugreport 组件会自动生成一个 minidump&#xff0c;截图如下&#xff1a; 作…

tcpdump 抓包

一、Tcpdump抓包 抓取端口为2008的数据包 抓包文件内容 抓取到的内容保存在文件中&#xff0c;可以通过wireshark分析 二、tcpdump的一些命令 tcpdump和ethereal可以用来获取和分析网络通讯活动&#xff0c;他们都是使用libpcap库来捕获网络封包的。 ​在混杂模式下他们可以监…

Oracle-主备切换问题(BUG-31747989)

背景: 用户在Oracle Rac 19.6版本通过switchover方式进行主备切换&#xff0c;在备切主完成之后&#xff0c;进行open的过程中&#xff0c;状态长时间无法完成疑似hang住。 问题: ​ Oracle Rac 19.6版本通过switchover方式进行主备切换,切换完成之后进行open&#xf…

100个开源手写人工智能算法(持续更新中)

你是否曾经对开源框架中算法的运行原理感到好奇&#xff1f;又是否曾经想过使用自己写的算法来进行机器学习&#xff1f; 现在&#xff0c;向您推荐一款基于 Python 语言的开源手写机器学习算法项目&#xff01; https://github.com/yuluxingchen/AI/ 这个项目中预计将包含了…

【10 浅学jsp】

浅学 jsp 一、jsp1. jsp介绍2. JSP执行流程3. JSP的本质还是Servlet4. JSP语法4.1 注释4.2 代码块4.3JSP表达式4.4JSP声明 5. JSP指令page 指令include 包含指令包含 其他页面taglib 引入外部标签库 6. JSP细节6.1 pageContext 页面域对象 7. Servlet四大域对象小结8. MVC模型 …

利用MFC实现一个托盘功能

文章目录 1.将主窗口隐藏起来&#xff0c;并移除任务栏图标显示2. 制作系统托盘3. 右键托盘得到信息4. 选择信息栏触发事件5. 添加开机自启动与关闭开机自启动OnSetPowerBoot与OnCancelPowerBoot 右键点击托盘&#xff0c;弹出如下的图标 1.将主窗口隐藏起来&#xff0c;并移除…

Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/130264470 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 红胖子网络科技博…

怎么批量把heic格式转化jpg,3招快速解决

怎么批量把heic格式转化jpg&#xff1f;heic是一种新型的图像文件格式&#xff0c;是苹果独家搞出来的一个图片格式&#xff0c;它小巧玲珑&#xff0c;而且图像质量超好&#xff0c;专门给iOS11系统用户用的。这种格式比老JPEG更厉害&#xff0c;不仅图片质量好&#xff0c;而…

如何减少电脑内存占用或优化内存?

内存(Memory)是计算机一个重要的组成部件&#xff0c;也称为内存储器或主存储器。它可以暂时存放CPU中运算的数据&#xff0c;以及与硬盘等外部存储器交换的数据&#xff0c;是CPU和硬盘之间的桥梁。若电脑内存占用过高&#xff0c;这会影响到电脑运行的速度&#xff0c;那该如…

Redis的哈希槽分区

目录 1. 一致性算法分区的缺点2. 哈希槽分区3. Redis为什么是16384个槽 1. 一致性算法分区的缺点 可以参考一致性哈希算法分区这篇文章 2. 哈希槽分区 Redis集群中内置了16384个哈希槽。redis会根据服务器节点数量大致均等的将哈希槽映射到不同的节点 当写入一条数据&#x…

Java版本的工程项目管理系统源代码之工程项目管理系统面临的挑战

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 ​系统定义 工程项目管理企业不直接与该工程项目的总承包…

UE4/5多人游戏详解(六、多人游戏插件的菜单,创建会话设置和加入)

目录 简单的菜单 创建新的c类&#xff1a; 这里可能出现的报错&#xff1a; 菜单设置&#xff1a; 代码&#xff1a; UI创建&#xff1a; C类中创建按钮的指针&#xff1a; 子系统创建 创建会话函数&#xff1a; 创建会话后前往大厅&#xff1a; 重载函数 变量添加…

Java 线程

线程&#xff1a;线程是进程的组成部分&#xff0c;一个进程可以拥有多个线程&#xff0c;而一个线程必须拥有一个父进程。线程可以拥有自己的堆栈&#xff0c;自己的程序计数器和自己的局部变量&#xff0c;但不能拥有系统资源。它与父进程的其他线程共享该进程的所有资源。 …

PowerShell install Docker+docker-compoer

docker 前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口。 …

Linux搭建SVN服务器详细教程

前言 本文讲解 Linux 系统下如何搭建 SVN 服务器&#xff0c;详细说明各配置项的功能&#xff0c;最终实现可管控多个项目的复杂配置。 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统&#xff0c;通过采用分支管理系统的高效管理&#xff0c;实现最终集…

【转】使用Midjourney绘制小漫画

原帖地址:【Midjourney教程】设计麻瓜也能15分钟一篇小漫画 Midjourney能帮我画漫画,话不多说,下方成品图 Part 1 你想画什么 画漫画当然要有故事情节,你总得确定,你要画个啥?也就是专业人士说的画面分镜,当然咱们是“野狐禅”,就不扯的太细,太细我也不会… 由于只…

软考中级软件评测师备考攻略

软件评测师属于软考中级&#xff0c;考试虽然没有软考高级难度大&#xff0c;但是会比软考初级要难&#xff0c;所以想要通过软件评测师考试还是需要花时间去用心备考的。 一、软件评测师职业前景&#xff1a; 随着互联网技术的不断发展&#xff0c;软件评测师的市场需求也会…