Day975.如何使用JWT结构化令牌 -OAuth 2.0

如何使用JWT结构化令牌

Hi,我是阿昌,今天学习记录的是关于如何使用JWT结构化令牌的内容。

OAuth 2.0 规范并没有约束访问令牌内容的生成规则,只要符合唯一性、不连续性、不可猜性就够了。这就意味着,可以灵活选择令牌的形式,既可以是没有内部结构且不包含任何信息含义的随机字符串,也可以是具有内部结构且包含有信息含义的字符串。


一、JWT 结构化令牌

关于什么是 JWT,官方定义是这样描述的:

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。

这个定义是不是很费解?我们简单理解下,JWT 就是用一种结构化封装的方式来生成 token 的技术。

结构化后的 token 可以被赋予非常丰富的含义,这也是它与原先毫无意义的、随机的字符串形式 token 的最大区别。结构化之后,令牌本身就可以被“塞进”一些·有用的信息·,比如小明为小兔软件进行了授权的信息、授权的范围信息等。

或者,可以形象地将其理解为这是一种“自编码”的能力,而这些恰恰是无结构化令牌所不具备的。

JWT 这种结构化体可以分为 HEADER(头部)、PAYLOAD(数据体)和 SIGNATURE(签名)三部分。

经过签名之后的 JWT 的整体结构,是被句点符号分割的三段内容,结构为 header.payload.signature 。

比如下面这个示例:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJVU0VSVEVTVCIsImV4cCI6MTU4NDEwNTc5MDcwMywiaWF0IjoxNTg0MTA1OTQ4MzcyfQ.
1HbleXbvJ_2SW8ry30cXOBGR9FW4oSWBd3PWaWKsEXE

注意:JWT 内部没有换行,这里只是为了展示方便,才将其用三行来表示。

JWT 令牌看起来也是毫无意义的、随机的字符串啊。

确实,你直接去看这个字符串是没啥意义,但如果把它拷贝到https://jwt.io/ 网站的在线校验工具中,就可以看到解码之后的数据:

图1 由在线校验工具解码后的JWT令牌

再看解码后的数据,你是不是发现它跟随机的字符串不一样了呢。很显然,现在呈现出来的就是结构化的内容了。

HEADER 表示装载令牌类型和算法等信息,是 JWT 的头部。其中,typ 表示第二部分 PAYLOAD 是 JWT 类型,alg 表示使用 HS256 对称签名的算法。PAYLOAD 表示是 JWT 的数据体,代表了一组数据。其中,sub(令牌的主体,一般设为资源拥有者的唯一标识)、exp(令牌的过期时间戳)、iat(令牌颁发的时间戳)是 JWT 规范性的声明,代表的是常规性操作。更多的通用声明,可以参考RFC 7519 开放标准。不过,在一个 JWT 内可以包含一切合法的 JSON 格式的数据,也就是说,PAYLOAD 表示的一组数据允许我们自定义声明。SIGNATURE 表示对 JWT 信息的签名。那么,它有什么作用呢?可能认为,有了 HEADER 和 PAYLOAD 两部分内容后,就可以让令牌携带信息了,似乎就可以在网络中传输了,但是在网络中传输这样的信息体是不安全的,因为在“裸奔”啊。所以,还需要对其进行加密签名处理,SIGNATURE 就是对信息的签名结果,当受保护资源接收到第三方软件的签名后需要验证令牌的签名是否合法。


二、令牌内检

什么是令牌内检呢?授权服务颁发令牌,受保护资源服务就要验证令牌。同时呢,授权服务和受保护资源服务,它俩是“一伙的”。受保护资源来调用授权服务提供的检验令牌的服务,把这种校验令牌的方式称为令牌内检。

有时候授权服务依赖一个数据库,然后受保护资源服务也依赖这个数据库,也就是说的“共享数据库”。

不过,在如今已经成熟的分布式以及微服务的环境下,不同的系统之间是依靠服务而不是数据库来通信了,比如授权服务给受保护资源服务提供一个 RPC 服务。

如下图所示。

图2 授权服务提供接口服务,供受保护资源校验令牌

那么,在有了 JWT 令牌之后,就多了一种选择,因为 JWT 令牌本身就包含了之前所要依赖数据库或者依赖 RPC 服务才能拿到的信息,比如上面提到的哪个用户为哪个软件进行了授权等信息。


三、JWT 是如何被使用的?

有了 JWT 令牌之后的通信方式,就如下面的图 3 所展示的那样了,授权服务“扔出”一个令牌,受保护资源服务“接住”这个令牌,然后自己开始解析令牌本身所包含的信息就可以了,而不需要再去查询数据库或者请求 RPC 服务。

这样也实现了上面说的令牌内检。

图3 受保护资源服务可直接解析JWT令牌

在上面这幅图中呢,为了更能突出 JWT 令牌的位置,简化了逻辑关系。

实际上,授权服务颁发了 JWT 令牌后给到了小兔软件,小兔软件拿着 JWT 令牌来请求受保护资源服务,也就是小明在京东店铺的订单。很显然,JWT 令牌需要在公网上做传输。

所以在传输过程中,JWT 令牌需要进行 Base64 编码以防止乱码,同时还需要进行签名及加密处理来防止数据信息泄露。如果是自己处理这些编码、加密等工作的话,就会增加额外的编码负担。好在,可以借助一些开源的工具来帮助我们处理这些工作。比如,在下面的 Demo 中,给出了开源 JJWT(Java JWT)的使用方法。


JJWT 是目前 Java 开源的、比较方便的 JWT 工具,封装了 Base64URL 编码和对称 HMAC、非对称 RSA 的一系列签名算法。

使用 JJWT,只关注上层的业务逻辑实现,而无需关注编解码和签名算法的具体实现,这类开源工具可以做到“开箱即用”。

这个 Demo 的代码如下,使用 JJWT 可以很方便地生成一个经过签名的 JWT 令牌,以及解析一个 JWT 令牌。

String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth";//密钥
Key key = new SecretKeySpec(sharedTokenSecret.getBytes(),
                SignatureAlgorithm.HS256.getJcaName());

//生成JWT令牌
String jwts=
Jwts.builder().setHeaderParams(headerMap).setClaims(payloadMap).signWith(key,SignatureAlgorithm.HS256).compact()

//解析JWT令牌
Jws<Claims> claimsJws =Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jwts);
JwsHeader header = claimsJws.getHeader();
Claims body = claimsJws.getBody();  

使用 JJWT 解析 JWT 令牌时包含了验证签名的动作,如果签名不正确就会抛出异常信息。

可以借助这一点来对签名做校验,从而判断是否是一个没有被伪造过的、合法的 JWT 令牌。

异常信息,一般是如下的样子:

JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

以上就是借助开源工具,将 JWT 令牌应用到授权服务流程中的方法了。

为什么要绕这么大一个弯子,使用 JWT,而不是使用没有啥内部结构,也不包含任何信息的随机字符串呢?JWT 到底有什么好处?


四、为什么要使用 JWT 令牌?

使用 JWT 格式令牌的三大好处

  • 第一,JWT 的核心思想,就是用计算代替存储,有些 “时间换空间” 的 “味道”。当然,这种经过计算并结构化封装的方式,也减少了“共享数据库” 因远程调用而带来的网络传输消耗,所以也有可能是节省时间的。
  • 第二,也是一个重要特性,是加密。因为 JWT 令牌内部已经包含了重要的信息,所以在整个传输过程中都必须被要求是密文传输的,这样被强制要求了加密也就保障了传输过程中的安全性。这里的加密算法,既可以是对称加密,也可以是非对称加密。
  • 第三,使用 JWT 格式的令牌,有助于增强系统的可用性和可伸缩性。这一点要怎么理解呢?这种 JWT 格式的令牌,通过“自编码”的方式包含了身份验证需要的信息,不再需要服务端进行额外的存储,所以每次的请求都是无状态会话。这就符合了我们尽可能遵循无状态架构设计的原则,也就是增强了系统的可用性和伸缩性。

JWT 令牌也有缺点

JWT 格式令牌的最大问题在于 “覆水难收”,也就是说,没办法在使用过程中修改令牌状态

还是借助小明使用小兔软件例子,先停下来想一下。小明在使用小兔软件的时候,是不是有可能因为某种原因修改了在京东的密码,或者是不是有可能突然取消了给小兔的授权?这时候,令牌的状态是不是就要有相应的变更,将原来对应的令牌置为无效。但,使用 JWT 格式令牌时,每次颁发的令牌都不会在服务端存储,这样要改变令牌状态的时候,就无能为力了。

因为服务端并没有存储这个 JWT 格式的令牌。这就意味着,JWT 令牌在有效期内,是可以“横行无止”的。为了解决这个问题,可以把 JWT 令牌存储到远程的分布式内存数据库中吗?

显然不能,因为这会违背 JWT 的初衷(将信息通过结构化的方式存入令牌本身)。因此,通常会有两种做法:

  1. 一是,将每次生成 JWT 令牌时的秘钥粒度缩小到用户级别,也就是一个用户一个秘钥。这样,当用户取消授权或者修改密码后,就可以让这个密钥一起修改。一般情况下,这种方案需要配套一个单独的密钥管理服务。
  2. 二是,在不提供用户主动取消授权的环境里面,如果只考虑到修改密码的情况,那么我们就可以把用户密码作为 JWT 的密钥。当然,这也是用户粒度级别的。这样一来,用户修改密码也就相当于修改了密钥。

五、令牌的生命周期

万物皆有周期,这是自然规律,令牌也不例外,无论是 JWT 结构化令牌还是普通的令牌。

它们都有有效期,只不过,JWT 令牌可以把有效期的信息存储在本身的结构体中。具体到 OAuth 2.0 的令牌生命周期,通常会有三种情况。

  • 第一种情况是令牌的自然过期过程,这也是最常见的情况。这个过程是,从授权服务创建一个令牌开始,到第三方软件使用令牌,再到受保护资源服务验证令牌,最后再到令牌失效。同时,这个过程也不排除主动销毁令牌的事情发生,比如令牌被泄露,授权服务可以做主让令牌失效。
  • 生命周期的第二种情况,访问令牌失效之后可以使用刷新令牌请求新的访问令牌来代替失效的访问令牌,以提升用户使用第三方软件的体验。
  • 生命周期的第三种情况,就是让第三方软件比如小兔,主动发起令牌失效的请求,然后授权服务收到请求之后让令牌立即失效。什么情况下会需要这种机制,也就是想一下第三方软件这样做的 “动机”,毕竟一般情况下 “很难放弃已经拥有的事物”。比如有些时候,用户和第三方软件之间存在一种订购关系,比如小明购买了小兔软件,那么在订购时长到期或者退订,且小明授权的 token 还没有到期的情况下,就需要有这样的一种令牌撤回协议,来支持小兔软件主动发起令牌失效的请求。作为平台一方比如京东商家开放平台,也建议有责任的第三方软件比如小兔软件,遵守这样的一种令牌撤回协议。

将以上三种情况整理成了一份序列图。同时,为了突出令牌,将访问令牌和刷新令牌,特意用深颜色标识出来,并单独作为两个角色放进了整个序列图中。

图4 令牌生命周期


六、总结

OAuth 2.0 的核心是授权服务,更进一步讲是令牌,没有令牌就没有 OAuth,令牌表示的是授权行为之后的结果。一般情况下令牌对第三方软件来说是一个随机的字符串,是不透明的。

大部分情况下,提及的令牌,都是一个无意义的字符串。但是,人们“不甘于”这样的满足,于是开始探索有没有其他生成令牌的方式,也就有了 JWT 令牌,这样一来既不需要通过共享数据库,也不需要通过授权服务提供接口的方式来做令牌校验了。

这就相当于通过 JWT 这种结构化的方式,在做令牌校验的时候多了一种选择。

  1. 有了新的令牌生成方式的选择,这就是 JWT 令牌。这是一种结构化、信息化令牌,结构化可以组织用户的授权信息,信息化就是令牌本身包含了授权信息。
  2. 令牌在 OAuth 2.0 系统中对于第三方软件都是不透明的。需要关心令牌的,是授权服务和受保护资源服务。
  3. JWT 令牌的失效问题。使用了 JWT 令牌之后,远程的服务端上面是不存储的,因为不再有这个必要,JWT 令牌本身就包含了信息。那么,如何来控制它的有效性问题呢?

两种建议,一种是建立一个秘钥管理系统,将生成秘钥的粒度缩小到用户级别,另外一种是直接将用户密码当作密钥。


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

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

相关文章

天然气井远程监控解决方案

天然气井远程监控解决方案 一、项目背景 随着天然气开发规模日益增长&#xff0c;天然气井的数量也在不断增加。且位置分散环境恶劣。传统的人工巡检方式越来越不能满足天然气井的生产需求和安全保障。天然气井井由储罐和集气站组成。 集气站通过计量站将天然气输入储罐或由集…

深入学习 Mybatis 的四大组件源码

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

社会心理学(1) 社会心理学的定义

今天开始 我们一起学习一门课程 社会心理学 社会心理学 他是 应用心理学 或者 心理学专业的一个必修课 吴江霖教授说过 心理学应该分为两大分支 生理心理学 和 社会心理学 如果认同他的观点 那么 社会心理学可谓是相当重要了 社会心理学的定义之广可以说 有多少社会心理学教…

【MySQL数据库一】MySQL数据库初体验

MySQL数据库初体验 1.数据库基本概念1.1 数据Data1.2 表1.3 数据库1.4 数据库管理系统1.5 数据库系统 2.数据库的发展3.主流的数据库介绍3.1 SQL Server&#xff08;微软公司产品&#xff09;3.2 Oracle &#xff08;甲骨文公司产品&#xff09;3.3 DB2&#xff08;IBM公司产品…

【Spark基础编程】 第8章 Spark MLlib

系列文章目录 文章目录 系列文章目录前言【 第8章 Spark MLlib 】8.1 Spark MLlib简介8.1.1 什么是机器学习8.1.2 基于大数据的机器学习8.1.3 Spark 机器学习库MLLib 8.2 机器学习工作流8.2.1 机器学习流水线概念8.2.2 构建一个机器学习流水线 8.3 特征抽取、转化和选择8.4 分类…

【Linux】进程间的通信之共享内存

进程间的通信之共享内存 一、system V 内存共享原理二、共享内存的使用1、ftok函数2、shmget函数3、shmat函数4、shmdt函数5、shmctl函数6、代码使用 三、一些细节的补充 一、system V 内存共享原理 利用内存共享进行进程间的通信的原理其实分为以下几个步骤&#xff1a; 在物…

Mysql数据库初体验

Mysql数据库初体验 一、数据库的基本概念1.数据&#xff08;Data&#xff09;2.表3.数据库4.数据库管理系统&#xff08;DBMS)5.数据库系统 二、数据库系统发展史1.第一代数据库2.第二代数据库3.第三代数据库 三、当今主流数据库介绍四、数据库分类1.关系数据库2.关系型 SQL 数…

mybatis-plus分页查询(springboot中实现单表和多表查询)

一、mybatis-plus单表查询 使用mybatis-plus实现单表分页查询 非常方便&#xff0c;主要操作步骤如下&#xff1a; 配置分页查询拦截器进行分页查询 1.首先&#xff0c;打开mybatis-plus官网的插件&#xff08;插件主体&#xff09; 或者点击mybatis-plus插件 我是配置在s…

基于Java汽车在线租赁管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

C语言-关键字

关键字就是c语言已经定义好的名字&#xff0c;直接可以拿过来使用&#xff0c;不需要再次定义 1 数据类型相关的关键字 用于定义变量或者类型 定义变量的语法结构&#xff1a; 类型 变量名&#xff1b; 拓展&#xff1a;变量名属于标识符&#xff0c;标识符&#xff08;变量…

希尔贝壳参与构建可信人工智能数据空间,助力大模型行业应用落地

2023年5月30日&#xff0c;由中国信息通信研究院、浙江省经济和信息化厅、杭州市人民政府、中国人工智能产业发展联盟主办的杭州通用人工智能发展论坛在未来科技城圆满落幕。本次会议以“大模型应用机遇和挑战”为主题&#xff0c;众多产学研代表现场参会&#xff0c;共同探讨人…

路径规划算法:基于未来搜索优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于未来搜索优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于未来搜索优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

异常数据检测 | Python实现基于高斯概率分布的异常数据检测

文章目录 文章概述模型描述源码分享学习小结参考资料文章概述 高斯分布也称为正态分布。它可以被用来进行异常值检测,不过我们首先要假设我们的数据是正态分布的。不过这个假设不能适应于所有数据集。但如果我们做了这种假设那么它将会有一种有效的方法来发现异常值。 模型描述…

RK3288 Android8.1添加lvds以及gt9触摸屏(一)

我们公司的屏幕是分为两部分 1.lvds负责屏幕亮起&#xff0c;显示UI 2.gt9触摸屏负责触摸点击反馈操作 现在先说lvds如何配置 RK的LVDS屏调试&#xff0c;主要是配置正确LVDS的dts&#xff0c;配置正确基本都是可以点亮的 1 首先拿到LVDS屏厂商给的屏规格书&#xff0c;规格…

哪个公司的 CEO 不想拥有一个自己的数字克隆?

⚠️ FBI Warning&#xff1a;本文纯属作者自娱自乐&#xff0c;数字人的观点不代表 CEO 本人的观点&#xff0c;请大家不要上当受骗&#xff01;&#xff01; 哪个公司的 CEO 不想拥有一个自己的数字克隆&#xff1f; 想象&#x1f914;一下&#xff0c;如果 CEO 数字克隆上线…

ISP下载原理分析

STM32的启动方式&#xff0c;系统存储器启动就是通过ISP下载 ISP简介 ISP下载是指可以通过串行外设&#xff0c;直接将程序下载Flash中&#xff0c;然后自动运行程序的启动方式。 ISP的时候需要用到bootloder(自举程序)&#xff0c;bootloader存储在STM32内部的自举ROM存储器…

wordpress去除分类URL的categpory

前言 在日常使用Wordpress搭建网站时&#xff0c;发现文章或者分类页的URL地址中默认带有Category&#xff0c;URL层级过长会影响我们网站SEO的优化&#xff0c;也不利于用户体验。这里讲一下如何去除URL中categpory的方法。 操作 第一步先登录到WordPress后台&#xff0c;然…

【论说文】段落与结构

结构和段落 开头和结尾 怎么写开头呢&#xff1f;基本套路就是用三句话。即表达清楚三层意思&#xff0c;第一句话是用简短的话来概括材料&#xff0c;但是不要照抄。写论说文&#xff0c;不是就事论事&#xff0c;而是就事论理。第二句话是过渡句。第三句&#xff0c;写出来中…

IDEA整合GO并创建module工程

IDEA整合Go 安装包环境配置idea配置并创建test mode 安装包 1.去官网下载对应还的安装包 官网下载地址 我选择下载的window 版本&#xff1a; 直接按照对应的目录&#xff0c;然后点击下一步 环境配置 1.配置go环境变量 在高级环境变量PAHT中添加安装包的**/bin 目录&…

Java网络开发(Tomcat同步数据增删改查)—— 用Jsp语法实现同步请求的 增删改查

目录 引出显示所有数据到前端&#xff08;1&#xff09;前端代码&#xff1a;list.jsp&#xff08;2&#xff09;后端代码&#xff1a;CompanyListServlet.java 新增数据---转发类型信息---新增信息业务&#xff08;1&#xff09;在list.jsp页面点击添加&#xff08;2&#xff…