什么是JSON Web Token
JSON Web Token (JWT)是一个定义了一种精简、自包含用于各方之间使用JSON对象进行数据安全传输的开发标准(RFC 7519)。作为一种数字签名,他可以被验证和信任。JWTs可以使用HMAC算法或者RSA秘钥喘作为密钥进行签名。
让我们进一步的解释一下相关概念。
- 精简(Compact):因为JWTs数据量较小,所以它可以通过一个URL、POST参数或者是一个HTTP报文头进行传输,而较小的数据量则意味着更快的传输速度。
- 自包含(Self-contained):playload域包含了所有与用户相关的必须信息,避免了多次与数据库进行交互。
我们应该什么时候使用JSON Web Tokens?
JSON Web Tokens主要适用的场景如下:
- 鉴权(Authentication):这是JWT最常使用的场景。一旦用户登录后,随后每个请求中都应该包含JWT,以便能访问使用Token进行授权的路由、服务与资源。JWT开销较小这一特点,使它广泛用于实现单点登录功能。
- 信息交换(Information Exchange):可以被加密的特性使JSON Web Tokens成为一种较好的数据加密传输的方式,例如,使用公钥与私钥,我们可以确认信息发送者的真是身份,此外,因为header与payload参与签名计算,我们同时也可以确认数据内容是否被篡改。
JSON Web Token的结构
JSON Web Token包含以“.”分割的三部分内容:
- Header
- Payload
- Signature
通常一个JWT看起来都是下面这种格式
xxxxx.yyyyy.zzzzz
下面分别解释各部分内容
Header
header通常包含两部分:token的类型,固定值为JWT;计算hash的算法,例如HMAC SHA256或者RSA。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
这部分JSON数据使用Base64Url编码后作为JWT组成的第一部分。
Payload
token组成的第二部分是payload,它包含claims。claims是关于实体(通常指用户)与其他元数据的声明。claims包括三种类型:reserved、public与private。
- Reserved claims: 这部分内容非必须但建议使用,以使其更具可用性与互操作性。它主要包含:iss (issuer), exp (expiration time), sub (subject), aud (audience)
我们可以注意到claim中的name为了保持精简,像JWT一样只包含3个字符。
- Public claims: 使用JWTs可以定义这部分,但为了避免冲突,它们应该定义在IANA JSON Web Token Registry或者被定义成不同命名空间的URI中。
- Private claims: 这一部分为信息交换的自定义部分。
payload示例:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
payload使用Base64Url加密后作为JWT的第二部分。
Signature
使用密钥(secret)按照header中声明的加密算法,对header和payload进行计算便可得到JWT的第三部分——签名。
例如,使用HMAC SHA256suan’f算法计算签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名主要用于验证数据发送者的身份以及确认数据在传输过程中没有被篡改。
组装JWT
JWT最终展示为使用Base64计算与“.”分割的三段式字符串,在HTML和HTTP环境下更易传输与使用基于XML方式(例如SAML)传输显得更精简。
下图展示了一个完整的JWT:加密后的header与payload以及使用秘钥计算所得签名
如果你想动手尝试以便加深对JWT概念的理解,你可以使用jwt.io Debugger进行加密、验证及创建JWTs。
JSON Web Tokens是如何工作的
在鉴权过程中,当用户使用凭证(如:用户名与密码)登录系统后,不同于在服务端创建一个session并在cookie中写入标识的方式,服务端会直接返回一个JSON Web Token,并且这个令牌会必须被客户端使用本地存储或cookie保存下来。
无论这个用户任何时候去访问一个受保护的路由或资源时都要携带上一步骤获得的JWT,通常放在报文头Authorization中,这个报文头看起来就像这样:
Authorization: Bearer <token>
JWT使用的是一种无状态的鉴权机制,因为用户的状态没有被保存在服务端。服务端会检测Authorization报文头中的JWT是否有效,通过则能访问所请求的受限资源。因为所有的JWT都是自包含的,所有验证所需的必要信息都包含在JWT中,减少了与数据库的多次交互。
这种机制支持所有的API都可以设计成无状态,甚至可以访问底层的服务。使用cookie不在是必须的,发布API的域名可以不同,所以跨域访问资源不再是一个问题。
下图展示了这个过程:
为什么应该使用JSON Web Tokens
因为JSON格式本身存储就比XML要小,当它加密后数据量仍旧较少,JWT比SAML更精简。这个特点让JWT成为了HTML与HTML进行数据传输的更好选择。
安全层面,SWT仅能支持使用共享的秘钥进行HMAC对称加密签名,而JWT和SAML可以使用X.509证书标准框架内的公私钥密钥对进行签名。与对JSON进行签名对比,适用数字证书对XML进行签名没有任何模糊不清漏洞是非常困难的。
JSON解析是大多数编程语言类库都具备的基础功能,它可以直接的转换成对象,与之相反的,XML不具备这种文档到对象的天然属性,这就使得使用JWT比SAML更容易。
至于适用范围,JWT已经被应用于互联网领域。这就使得JWT在多平台客户端,特别是移动端处理JSON Web token方面的易用性更加突出。