什么是 JWT ?
JWT 全称为 Json Web Token,是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递 Json 对象,传递的信息经过数字签名,可以被验证和信任。
什么时候使用 JWT ?
JWT 用途广泛,例如 OAuth2、用户授权、服务器通信鉴权等。比如在用户授权的场景中,服务器端可在用户登录后生成符合 JWT 规范的 AccessToken,并发送回用户端,之后用户端可携带这个 AccessToken 向服务器请求授权资源。
JWT 里有什么?
我们先来看看 标准的 JWT 长什么样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
可见,JWT 包含三段信息,信息之间使用点号(.)分隔。
这三段信息分别为头部(Header)、载荷(Payload)、签名(Signature),下面我们来说说这几部分信息。
头部(Header)
头部信息为 Base64 编码的字符串,解码后为 Json 格式的字符串,示例如下:
{
"alg": "HS256",
"typ": "JWT"
}
该部分包含两个信息:当前 JWT 使用的签名算法,比如 HMAC SHA256 或者 RSA,当前 JWT的类型,即 JWT。
载荷(Payload)
载荷跟头部信息一样,也是为 Base64 编码的字符串,解码后示例如下:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
该部分包含 token 的信息(claims),这里包含一些约定的字段以及 JWT 生成时生产方自定义的字段,其中,约定的字段是非必须的,但是 JWT 规范中推荐携带上。规范中约定的字段有: iss(生成方)、exp(过期时间)、sub(主体)、iat(生成时间)等,具体可查看 JWT规范约定字段说明。自定义字段则可由生成方定义,字段名称不要和规范约定的字段冲突就行。需要注意的是不要在这部分信息中存放敏感信息,因为这些信息是没有加密的,只要拿到 jwt 使用 Base64 解码就能获取到。
签名(Signature)
签名部分用于信息的接收方确认当前 JWT 的合法性。要创建签名,你需要用到头部、载荷和密钥,首先将签名方法写在头部信息里,然后对头部和载荷信息进行签名。举个例子,如果使用 HMAC SHA256 算法,则该签名可以通过以下方式生成:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名可以保证 JWT 在传输的过程中没有被篡改,还有如果使用 RSA 做签名,也可验证 JWT 是否真的是生成者发来的,具有防抵赖性。
为什么使用 JWT?
首先,JWT 由 Base64-URL 字符串并以点号(.)组成,非常适合在 HTML 和 HTTP 环境中传输和解析,Json 格式相对于 XML 也显得更加紧凑和简洁。同时,JWT 在传输过程是无状态的,更契合当前分布式应用场景。
JWT 如何使用?
在用户鉴权场景中,当用户使用账号密码等方式成功登录后,服务端为当前用户生成一个 JWT 并返回,至此之后,这个 JWT 即为用户的鉴权标识,后续服务端通过验证 JWT 的合法性判断是否信任用户的请求。
需要注意的是,服务端需要为这个 JWT 设置一个过期时间,以免 JWT 泄露造成安全问题。还有就是不要在 JWT 中存放敏感信息,因为 JWT 并不会做数据加密。
当用户想要访问受保护的资源时,必须在请求中携带 JWT,通常的做法是在 HTTP 头 Authorization 中使用 Bearer 协议,内容如下所示:
Authorization: Bearer <token>
这是一种无状态的鉴权机制,服务端通过校验 Authorization 头中的 JWT,如果存在,则这个用户可以访问受保护的资源,如果这个 JWT 包含一些必要的用户信息,这个方式在某些情况下还可以减少从数据库读取用户信息的次数,提升访问速度。
使用 Header 传输 JWT,你要注意不要存放过多的信息到 JWT,这会导致 JWT 过于臃肿,影响传输速度,甚至还有一些服务器会限制 Header 的长度不超过 8KB,真的要存储这么多信息的话,请考虑使用别的方案。
总结
在文章中我们了解了什么是 JWT、JWT 的组成及原理以及如何使用 JWT,JWT 提供一个简洁并且保证安全的规范用于信息的传输,它比基于 XML 的 SAML 更加紧凑和简洁,更加适用于 HTML 和 HTTP 环境的传输和解析,在安全方面,JWT 使用自洽的签名算法,可以使用相对简单的对称算法以及更高安全性的非对称公私钥算法。JWT 在用户鉴权、信息传输及交换等场景具有很大的发挥空间。