JWT是个什么鬼?

【答疑解惑作者 / Edison Zhou

这是恰童鞋骚年的第269篇原创内容


前面一篇我们了解了微服务安全认证架构是如何演进而来的,但是发现v2.5架构仍然较重,有没有轻量级一点的方法呢?其实业界早已有了实践,它就是基于JWT的安全认证架构。JWT到底是个什么鬼呢?本篇为你解答!

1v2.5版本存在的问题

在v2.5版本Token+Gateway模式下,适合于大部分微服务场景,但是当网站流量很大的时候,对AuthService的访问压力也会比较大,它很可能会成为性能和扩展性的瓶颈

MyShop v2.5版本:Token+Gateway

此外,对于很多对于安全不是很敏感的微服务来说,集中状态校验就会显得很笨重。

2v2.6版本:JWT+Gateway

在业界实践上,很多企业都在采用基于JWT令牌的无状态安全认证架构,MyShop技术团队也探索出了v2.6版本,即基于JWT+Gateway的模式:

MyShop v2.6:JWT+Gateway

v2.6在v2.5的基础之上发展而来,主要区别如下:

(1)第二步中,v2.5使用的是透明应用令牌,而v2.6使用的是JWT令牌,JWT令牌是自包含数据和签名的;

(2)第四步和第五步,v2.5需要网关每次请求都去AuthService进行校验,而v2.6网关处则不用;此处,网关就可以自行进行令牌的解析和合法性校验;解析完成后,网关就可以得到用户标识信息并向后端微服务传递了;

画外音:这里的JWT令牌有点类似于单块架构阶段v1.x版本下的无状态Session,并且针对于微服务场景进行了扩展应用。

JWT+Gateway的这种做法简化了安全认证架构,降低了AuthService的压力,总体上来说是一种高性能和可扩展的架构,适用于大部分对安全要求不太敏感的微服务应用场景。为什么说是大部分对安全要求不敏感的场景呢,这就需要我们了解一下JWT的原理了。

3JWT的原理

JWT全程JSON Web Token,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。

JWT最主要的特点就是它定义了一种紧凑和自包含的JSON对象格式,通过它可以在多个系统或服务之间安全的传递信息,信息经过数字签名可以校验且是可信任的。

JWT主要用于 认证授权 和 信息交换 的场景,其令牌结构主要有如下图所示的3个部分组成,且不同部分之间用了一个 . 分隔:

JWT的三个组成部分

这三个组成部分分别是:Header头部、Payload消息体 以及 Signature签名。

画外音:JWT将消息体分为了Header和Payload,其实有点类似于HTTP协议,它也将请求体分为了Header和Body,Header里面一般放元数据,类似于信封上的寄件人和地址等,而Body里面则存放的是实际数据,类似于信封里面的主体内容。

下面我们来看一个JWT令牌的示例:

JWT令牌示例

我们先关注上图中的左半部分,可以看到,三个部分分别使用了不同的颜色标注了出来,并且通过 . 分隔开。

画外音:如果你没看到,那就仔细看一下!如果还没看到,那就打开放大看一下!

一般来说,我们都会通过一些工具例如jwt.io网站来查看JWT解码后的内容,也就是上图中的右半部分就是在jwt.io上进行解码后的内容。

可以看到,Header部分解码后的内容说明了这个令牌的类型是JWT,即JSON Web Token,它使用的算法是HS256算法。

然后,Payload部分解码后的内容说明了这个令牌的颁发者是谁(iss),颁发的时间(iat),令牌过期时间(exp)、这个令牌要颁发给谁(aud)以及目标用户是谁(sub)。这些信息也称为Claims,他们是官方定义的Public Claims。我们在实际使用中,也会定义一些Custom Claims,比如用户的角色信息(Role)等。

针对ASP.NET Core开发童鞋,推荐阅读晓晨的这篇文章实践IdentityServer:《IdentityServer4实战-基于角色的权限控制及Claim详解》,传送门:https://www.cnblogs.com/stulzq/p/8726002.html

最后,Signature部分则表明了整个JWT的验证方式是什么样子的,即一个签名公式。如果是采用HS256算法的话,就是下面这个公式:

base64Url(Header)+"."+base64Url(Payload)+"."+base64Url(Signature)

在jwt.io上,我们可以通过输入secret进行一个令牌的合法性的校验,如果不通过则会显示Invalid Signature,通过则显示Signature Verified.

JWT令牌校验

看完了JWT的三个组成部分,及其组装公式,我们可能会发现:

Header和Payload的内容是公开可见的,只要拿到Token就可以去类似jwt.io这种工具网站上进行Debug解析,那JWT真的安全吗?

画外音:JWT保证的安全可能是相对的,它不会保证传输信息的保密性,但它会保证信息的可依赖和不可篡改性(通过Signature实现)。因为Secret是保密的,所以即使一般用户拿到了你的token和算法,也无法篡改里面的数据(一旦篡改校验就会不通过)。换句话说,JWT令牌有点类似于现实世界中的签名支票,如下图所示。

签名支票

4JWT的实现方式

上面我们了解了JWT的原理,现在来看看JWT都是如何来实现的。目前,JWT主要有两种算法实现,一种是HMAC,另一种是RSA。

HMAC流程

首先,来看看HMAC的实现流程:

HAMC流程

Step1.客户端向AuthServer发出登录请求;

Step2.AuthServer校验用户身份,通过后生成JWT数据结构且采用某种HMAC算法+Secret对JWT进行签名,最后将这个签名后的JWT令牌返回给客户端;

Step3.客户端收到JWT后一般都会做本地存储,然后在调用微服务的时候都会带上JWT令牌;

Step4.微服务接收到客户端请求和JWT令牌时,会采用同样的Secret对JWT令牌进行解析和校验,通过后则返回处理后的数据,不通过则一般返回401。

由此看来,HMAC流程中,最重要的就是secret的保密,如果泄露,则整个流程不再安全。

RSA流程

然后,来看看RSA的实现流程:

RSA流程

RSA流程总体上来说和HMAC类似,不同的是AuthServer在颁发JWT令牌的时候采用私钥Private Key进行签名,而微服务端ResourceServer在解析和校验JWT令牌的时候采用公钥Public Key进行签名。

可以看出,RSA流程比HMAC流程总体来说要安全一点,因为只有AuthServer一个地方需要保存私钥,私钥的泄露概率就小很多。其他的微服务端都使用公钥进行解签校验,但是不能够篡改加签。

画外音:其实就类似于对称加密 和 非对称加密的方式。

5JWT学习小结

本文通过MyShop v2.5存在的问题引出了使用JWT令牌的v2.6架构,并介绍了JWT的概念、原理 和 实现方式。最后,我们来总结一下JWT的优势及不足:

重点关注一下JWT的不足:

(1)无状态和吊销无法两全,如果某个用户令牌异常(比如有黑客在干坏事),我们想要吊销这个用户的令牌,但是却没有办法在AuthService上进行统一吊销,一般需要等到这个JWT令牌自然过期才能吊销。又假设我们在AuthService上对某个用户的信息进行了更新,那么相关的Claims信息也必须要等到这个老的JWT过期后重新登录或刷新后产生了新的JWT后才能更新。

(2)JWT的大小会随着Claims的数量增多,也会导致JWT的大小会变大,从而也会导致传输的开销增大

最后,我们可以对有状态的透明令牌和无状态的JWT令牌做一个小结:

两者各有适用场景,JWT令牌更适合于安全不敏感场景,透明令牌更适合于安全敏感场景。这里的敏感主要是指和钱、交易、支付相关的场景,以及金融、银行等业务之类的场景,这些场景可以采用集中式的有状态的透明令牌认证,其他的一般性的微服务应用场景则可以使用JWT。

画外音:对中小技术团队来说,特别是技术储备和实力都没那么强的团队,和钱相关的业务场景,宁慢三秒,不抢一秒,因为有时候想快那么一秒,可能就翻车了。

往期骚年快答

技术中台与业务中台有啥联系?

微服务架构中的BFF到底是个啥?

为何微服务项目都爱用单体仓库?

微服务安全认证架构如何演进而来的?

专注于开发技术与个人成长分享,

对你有用的公众号!

????点个赞和在看如何?

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

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

相关文章

[Redis6]发布和订阅

Redis6的发布和订阅 什么是发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 发布订阅命令行实现 打开一个客户端订阅channel1 打开另一个客户端&…

mysql innodb log_教你如何理解mysql中的innoDB log

前言:之前一直弄不清楚mysql里面bin log和innodb log文件的区别,在脑子里面一直有个疑问binlog日志文件已经可以用来进行数据库的日志备份恢复了,怎么又多了一个redo log文件了。相信也有很多人有这个疑惑,现在把整个过程文档整理出来&#x…

微服务框架Demo.MicroServer运行手册

一.背景说明:之前分享过一个微服务开发框架, “分享一个集成.NET CoreSwaggerConsulPollyOcelotIdentityServer4ExceptionlessApolloSkyWalking的微服务开发框架”,前两天在Github上收到一个Issues,是想我这边提供下完整的运行文档…

[Redis6]新数据类型_Bitmaps

Bitmaps 简介 现代计算机用二进制(位) 作为信息的基础单位, 1个字节等于8位, 例如“abc”字符串是由3个字节组成, 但实际在计算机存储时将其用二进制表示, “abc”分别对应的ASCII码分别是97、 98、 99&a…

mysql qps如何查看_一款查看mysql QPS的脚本

本脚本黏贴就可以使用绝对不坑人!!!(此脚本来源如一位大神网友)执行效果:脚本:#!/bin/bashPWEqipay20150504mysqladmin -P3306 -uroot -p$PW -r -i 1 ext |\awk -F"|" \"BEGIN{ count0; }"\{ if($…

.Net Core 自定义配置源从配置中心读取配置

配置,几乎所有的应用程序都离不开它。.Net Framework时代我们使用App.config、Web.config,到了.Net Core的时代我们使用appsettings.json,这些我们再熟悉不过了。然而到了容器化、微服务的时代,这些本地文件配置有的时候就不太合适…

[Redis6]Bitmaps与set对比

Bitmaps与set对比 但Bitmaps并不是万金油, 假如该网站每天的独立访问用户很少, 例如只有10万(大量的僵尸用户) , 那么两者的对比如下表所示, 很显然, 这时候使用Bitmaps就不太合适了&#xff0c…

MySQL分布式ID_分布式唯一ID系列(3)——数据库自增ID机制适合做分布式ID吗

数据库自增ID机制原理介绍在分布式里面,数据库的自增ID机制的主要原理是:数据库自增ID和mysql数据库的replace_into()函数实现的。这里的replace数据库自增ID和mysql数据库的replace_into()函数实现的。这里的replace into跟insert功能类似,不…

7-15 QQ帐户的申请与登陆 (25 分)(map做法+思路分析)

一:题目 实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。 输入格式: 输入首先给出一个正整数N(≤10 ​5 ​​ ),随后给出N行指令。每行指令的格式为:“命令符&a…

[Redis6]新数据类型_HyperLogLog

HyperLogLog 简介 在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用Redis的incr、incrby轻松实现。 但像UV(UniqueVisitor,独立访客)、独立IP数…

每天都在支付,你真的了解信息流和资金流?

作为一个财务类的产品经理,除了每天被财务“虐待”千百遍,还需要对整个资金流向很清楚:钱给谁,怎么给,怎么做逆向流程,谁参与容错等。财务很在意资金的流转安全,但又极不愿意花时间关注它。诸如…

mysql改表字段类型导致数据丢失_故障分析 | 记一次 MySQL 主从双写导致的数据丢失问题【转】...

一、问题起源不久前用户反馈部门的 MySQL 数据库发生了数据更新丢失。为了解决这个问题,当时对用户使用的场景进行了分析。发现可能是因为用户在两台互为主从的机器上都进行了写入导致的数据丢失。如图所示,是正常和异常情况下应用写入数据库的示例。随后…

[Redis6]新数据类型_Geospatial

Geospatial 简介 Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询&…

《Apache SkyWalking实战》送书活动结果公布

截至2020.07.31 本次送书活动 这么多Apache顶级项目,SkyWalking为何一枝独秀?,本次很多同学在看到活动的书,自行就到网上购买了书。下面把Top 8的留言截图给大家回顾一下。以下8位同学将获赠书籍一本:landon、田晓青、…

7-16 一元多项式求导 (20 分)(详解+题目分析)

7-16 一元多项式求导 (20 分) 1:题目 设计函数求一元多项式的导数。 输入格式: 以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 输出格式: 以与输入相同的格式输出导数多项式非零项的系数和…

[MyBatisPlus]通用枚举

通用枚举 数据库表添加字段sex 创建通用枚举类型 package com.xxxx.mybatisplus.enums;import com.baomidou.mybatisplus.annotation.EnumValue; import lombok.Getter;Getter public enum SexEnum {MALE(1,"男"),FEMALE(2,"女");EnumValue // 将注解所标…

信创产业发展应不忘初心牢记使命

受国际大环境影响,信创市场国产化替代步伐已然加速。由于其中存在巨大的商机,信创市场中已然出现一些乱象。有的厂商拿洋技术标榜和宣传自主;有的厂商全国各地跑马圈地建产业园,进而向当地政府要政策要市场;有的厂商恶…

mysql采用 级触发_Mysql高级之触发器(trigger)

触发器是一类特殊的事务 ,可以监视某种数据操作(insert/update/delete),并触发相关操作(insert/update/delete)。看以下事件:完成下单与减少库存的逻辑Insert into o (gid,num) values (2,3); // 插入语句Update g set goods_num goods_num - 3 where id 2;// 更新…

[MyBatisPlus]代码生成器

代码生成器 引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.freemarker</groupId…

飞机游戏项目完整代码(详解JAVA300集)

一&#xff1a;简介 这是一个可以通过键盘移动飞机位置 然后可以躲避 炮弹的打击 &#xff0c;游戏结束为 当炮弹与飞机发生碰撞 则 最后显示出飞机存活的时长 代表游戏结束 二&#xff1a;上码 1&#xff1a;运行游戏的类 package src.src.cn.wyj.飞机;import java.awt.Co…