Json Web Token(JWT)简介

作者:JAY 2018-09-15

上篇博客介绍了Token的基本原理和最常用的Access Token方案。本篇接着讲Token的另一种姿势:Json Web Token。


和传统的cookie-session方案原理一样,在服务器存token得考虑怎么扩展成单点登录。举个例子,假设你公司有站点A和站点B,需要打通用户体系,用户只要在其中一个站点登录,在另一个站点就能自动登录。有两种思路,第一种是把用户模块跟业务模块剥离开来,每个站点都使用通用的登录模块,这开发起来工作量较大。第二种是服务器就不要存token了,直接存在客户端就行了,我们只需要保证客户端的token是可信的。Json Web Token就是第二种思路的一个代表。


JWT简介

Json Web Token,简称JWT。JWT加入了签名:服务器使用密钥对token数据进行签名并发给客户端,但服务器并不储存token本身。由于客户端拿不到密钥,因此无法伪造这个签名。服务器每次收到token,只需要校验签名通过,就认为这个token是有效的。

签名的思路跟cookie防篡改的思路相似,可以参考我之前的一篇博客《详解cookie》。


JWT储存和传输的方式和普通的token一样:可以存在cookie里,也可以存在localStorage里,或者其他任何方式;可以用cookie传输,也可以用http header,甚至可以作为请求的参数。不过JWT的数据量比传统的token更大,如果没有使用Http2等技术,每次请求都会多一些字节。


JWT结构

JWT分为三部分,分别是Header(头部)、Payload(核心数据)、Signature(签名)。每个部分分别使用Base64URL编码,并用点隔开,即“Header.Payload.Signature”的格式。举个例子:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJuYW1lIjoiSmF5IiwiaWF0IjoxNTE2MjM5MDIyfQ.
jc9Z5Gg21ciFbWt0XofG_Fbof5w8NqW4KABJ1eezrns

上述例子中,红色标注部分为Header,紫色部分为Payload,蓝色部分为Signature。Header和Payload部分使用了Base64Url编码,是可逆的,分别解码之后得到两个json格式的数据,下文详细介绍。Signature为签名算法运算的结果,不需要再解码。


Base64编码和解码的方法可以参考我之前的另一篇博客《Base64编码原理》。


Header

{
 "alg": "HS256",
 "typ": "JWT"
}

Base64解码红色部分,得到json格式的头部。alg(algorithm)是签名算法,typ是token的类型。加密算法可以选择SHA、RSA等多种,这里用的是HMAC SHA256。


Payload

{
 "name": "Jay",
 "iat": 1516239022
}

Base64解码紫色部分,得到json格式的核心内容,即我们实际用到的内容。由于服务器不再储存token信息,有些非机密数据可以存在这里,比如用户标识、过期时间等等。官方规定的字段如下(非必填):

其他字段可以根据需求自定义。但JWT默认是不加密的, 请勿储存机密的信息。


Signature

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

签名不再是json格式,也不需要base64编码。Header里已经声明了我们使用HMAC SHA256算法,因此签名就是用这个算法对编码后的Header和Payload数据进行加密。加密使用的密钥(secret)只有服务器才有,不泄漏给用户,所以用户无法伪造签名。


如果有多台服务器,那么只需要在服务器之间共享密钥(secret) ,收到用户的token时校验签名无误,就可以确定这个token里存的数据是友军服务器写入的,可以相信里面的数据。


JWT使用场景

先抛出一个问题:如何吊销一个已经签发出去的JWT?

由于服务器已经不储存Token了,通常是以客户端储存的JWT中,payload的“exp”字段来作为过期时间。一旦签发,在有效期内服务器都认为它是有效的。如果要设计一套吊销机制,就不得不在服务器储存已吊销的token的信息,每次收到token再查一下数据库看看是否已经被吊销了。但这样做就失去了“不在服务器储存token”的优势了,还不如使用其他方案替代。


JWT不如传统的token安全,也不可控。因此使用时要注意:


由于上述问题,我个人并不推荐使用JWT进行用户验证。JWT更适合用于多台服务器之间交换信息,灵活使用的话,可以有效降低开发和部署成本。



参考文献

  1. https://jwt.io/



本文未经许可禁止转载,如需转载请联系 JAY@oonne.com



TOP