JSON Web Tokens(JWT)的理解

前言

虽然前两年系统中就已经应用了JWT作为token用来鉴权认证等,大概知道那么回事,但是经常交流过程中,面对别人的疑问没法给一个深入的解答,所以重新梳理了下JWT相关知识。

1.什么是JWT?

JWT官网
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,以JSON对象的方式在各方之间安全地传输信息,因为是基于数字签名所以可以进行验证和信任,常用的算法比如有HMAC、RSA等等。

2.JWT数据结构

JWT由三部分组成,以"点"(.)作为分隔符,看起来格式这样的xxx.yyy.zzz

接下来看一下这三部分的具体构成:

  • Header
    Header是JWT的第一部分,包含算法类型和token类型的说明,举例如下,算法是用的HS256指的是HMACSHA256,token类型是JWT。
    HMACSHA256不了解?可以看看对算法介绍的这一篇密码学相关知识梳理
    Base64Url不了解?Base64和Base64Url区别是什么?下文会对Base64和Base64URL做一些简单介绍。
例子:Header内容
{
 "alg": "HS256",
 "typ": "JWT"
}
对该json进行Base64Url编码得到
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,也就是xxx.yyy.zzz的xxx部分的值。
  • Payload:载荷
    Payload是JWT第二部分,我们把数据放在这部分,举例如下
例子:Payload内容
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
对该json进行Base64Url编码得到
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
  • Signature:签名
    Signature是JWT第三部分,是对前两块内容的签名值,比如以签名算法HMACSHA256为例
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
按照上面计算规则:
 base64UrlEncode(header) + "."+base64UrlEncode(payload)=xxx.yyy
也就是说第三部分的值就是对“xxx.yyy”进行HMACSHA256摘要计算,这里secret假设等于“123456789”
计算出来的第三部分值:S2ZL7D-D3VeduQ44Cy2qLRFxHV43gRGSZtlfJ2MJ57g

最后把上面三部分拼接到一起组成完整的JWT如下,从上面的计算规则我们可以发现,JWT的安全性其实就是基于算法的原理,比如用的HMACSHA256,那么密钥就是安全的保证,别人拿不到密钥就无法伪造,无法篡改JWT。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.S2ZL7D-D3VeduQ44Cy2qLRFxHV43gRGSZtlfJ2MJ57g

2.1一些理解:

  • Q1:Payload是否可以存敏感数据?
  • A1:不能,Header和Payload都只是对数据进行Base64Url编码而已,了解Base64的话,应该知道这个不是加密,第三方拿到编码数据可以直接解码,所以不要放任何敏感数据,除非额外对数据又进行加密处理。
  • Q2:第三方是否可以伪造JWT?是否可以篡改Payload里面的数据?
  • A2:从上面第三部分Signature签名值计算规则,我们可以看到,是用HMACSHA256算法以及密钥key计算Header和Payload的摘要值,密钥key是服务端私有的,理论上攻击者没有密钥key就无法生成出一样的签名值,所以结论是无法伪造jwt,同样的篡改Payload里面的数据,服务端计算出来的签名值就会不匹配,这样就可以认为被篡改了,直接拒绝服务,所以密钥key是关键,不能泄露。
  • Q3:假设如下截图中消息是xxx.yyy的值,HMACSHA256签名后在进行Base64Url编码得到的是如下截图中的结果A'还是结果B?
  • A3:答案是B,详细解释如下:
    如下截图中消息是base64UrlEncode(header) + "." +base64UrlEncode(payload),也就是待签名内容,使用密钥key通过计算,结果A是HMACSHA256计算的摘要值字节数组转十六制的值64个字符(sha256计算摘要值是256bit,1个字节8bit,256bit对应32个字节,1个字节用2位16进制表示,所以结果A是64位),然后对结果A进行Base编码得到结果A' 88个字符(64位十六进制读取的时候每一位当做一个字符读取),结果B是对HMACSHA256计算出来的32个字节原始二进制直接进行Base64编码得到的是44个字符,结果B是才是正确的流程,结果A为什么会长度多一倍呢?因为签名值32个字节转成16进制后,在计算Base64的读取十六进制的时候是以字符读取,变成了64个字节,一出一进长度翻了一倍。

3.Base64和Base64Url

3.1Base64算法

Base64主要是对给定的字符和字符编码(如ASCII码,UTF-8码)对应的十进制数为基准,做编码操作:
1.将给定的字符串以字符为单位转换为对应的字符编码(如ASCII码)
2.将获得的字符编码转换为二进制码
3.对获得的二进制码做分组转换操作,每3个8位二进制码为一组,转换为每4个6位二进制码为一组(不足6位时地位补0),这是一个分组变化的过程,3个8位二进制码和4个6位二进制码的长度都是24位(38=46=24)
4.对获得的4个6位二进制码补位,向6位二进制码添加2位高位0,组成4个8位二进制码
5.将获得的4个8位二进制码转换为十进制码
6.将获得的十进制码转换为Base64字符表中对应的字符
举例如下:ASCII码字符编码
对字符串“A”进行Base64编码,如下表示:

字符                     A
ASCII码                  65
二进制码                 01000001
4-6二进制码              010000      010000
4-8二进制码              00010000    00010000
十进制码                 16          16
字符表映射码              Q          Q           =       =

字符“A‘经过Base64编码后得到"QQ=="这样一个字符串,Base64是以4个字符为单位,其长度只能是4个字符的整数倍,不满足时就用等号补位。

3.2 Base64Url

查看Base64字符映射表我们可以知道有一些字符比如"/"、“+”、“=”,像这种字符在Url中有特殊的意义,所以我们需要替代这些字符,替代规则是“-”替代“+”,"_"替代“/”,"="直接去掉,这就是Base64Url编码方式。

  • Base64Url编码的流程
1.明文使用BASE64进行编码
2. 在BASE64的基础上进行以下的编码:
   去除尾部的"="
   把"+"替换成"-"
   把"/"替换成"_"
  • Base64Url解码的流程
1.替换字符
    把"-"替换成"+"
    把"_"替换成"/"
   (计算Base64Url编码长度)%4
    结果为0,不做处理
    结果为2,字符串末尾添加"=="
    结果为3,字符串末尾添加"="
 2、使用Base64解码密文,得到原始的明文

3.2.1Base64Url解码问题

交流的时候有个同事刚好提出为什么补等号的时候, (计算Base64Url编码长度)%4结果为0,2,3,没有为1的情况?
接下来看一下这个计算过程,前面提到Base64编码规则每3个8位二进制码为一组,转换为每4个6位二进制码为一组(不足6位时地位补0),假设我们对一组字节编码,比如22个字节,每三个字节一组,最后剩下一个字节(22mod3=1),23个字节分组后剩下2个字节(23mod3=2),21个字节则正好分成7组,所以分组过程中只可能剩1个字节或者2个字节,下面对剩1个和2个字节的分析

  • 1个字节
    从前面对字符"A"编码过程也可以看到,如果一个字节比如01000001,拆成4-6二进制的时候是010000和010000(本来是拆成6位010000和01,不足6位的补0),4-8二进制变成00010000和00010000,然后在转10进制然后从Base64映射对应的字符得到两个字符QQ,Base64是4个字符位单位,所以补两个"=="。
  • 2个字节
    从上面剩1个字节的分析可以很容易的看出,2个字节拆成4-6二进制的时候对应3个4-6,4-8二进制也是3个,最后得到字符3个,补一个“=”号。
    所以转成Base64后,可能刚好分组,或补1个等号或2个等号这三种,不存在补3个等号的。

3.3扩展的一些思考

我们将JWT用作系统token机制,用户登录后服务端颁发token,后续请求头带上token,服务端检验该token是否合法来判断用户的合法性。

  • 对于现在很多单页面应用比如基于AngluarJS,Vue,拿到token后存在了localstorage中,后续请求在从localstorage中取出,这样是否安全?是否有更好的方案?
  • 我们在以前pc时代通过session,cookie机制进行会话跟踪,那这两种机制本质上的差别是什么?
    这两个问题因为还没有完全想明白也没有一个完美的解决方案,所以暂时抛出来记录一下。

4.附录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容