JWT 的结构分析


JWT

数据组成:

  1. header
  2. payload
  3. signature

一条 JWT 的数据就像下面这样, 由小数点(dot) 将它们分割为三部分, 分别对应上述的 header, payload, signature。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoieHR5dW5zIn0.W8MHwdmOrtQ581irVoe6zRwQke0VVCcky2s8kTC3sSg

其中前两段数据可以使用 base64url 解码为如下格式 (base64url 是在 base64 的基础上将 = 进行省略, + 转换为 -, / 转换为 _ 以避免与 url 内容发生冲突):

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

可以将它们看作是两个 json 字符串对象, 其中在 header 这个数据对象中存放了两条数据: typ 和 alg, 在 JWT 中将它们称作 Claim, 即 header 中的 Claims 长度为 2。同理 payload 中存放了一条键为 name 的 Claim, 它的值为 xtyuns

header 用于存放 JWT 基本信息, 如: 签名算法 (alg), jwt 类型 (typ)。

其实 JWT 还规定了另外两个关键字 cty (Content Type) 和 kid (Key Id) 但是它们都是可选内容, 且一般都用不到。

payload

payload 用于存放自定义信息, 当然你也可以将它们放在 header 中, 但是一般没人会这么做。

JWT 在 payload 中也规定了 7 个关键字:

nbf: JWT 的生效起始时间 (Not Before)
exp: JWT 的到期时间 (Expiration Time)
iat: JWT 的签发时间 (Issued At)
iss: JWT 的签发人 (Issuer)
sub: JWT 的主题 (Subject)
aud: JWT 的接收者 (Audience)
jti: 本条 JWT 数据的 id(JWT ID)

这些 Claim 都是可选的, 但是如果设置了其中的一些 Claim 且满足 iat > NOW || nbf > NOW || exp < NOW 时, 该条 JWT 数据应该是无效的 (JWTVerificationException)

signature

signature 用于对 JWT 中的前两段数据进行签名, 保证数据无法被随意篡改, 加密算法需要与 header 中的 alg 属性相对应, 否则无法完成签名验证。

常见异常

当签发 JWT 数据的配置不正确或无法转换为 JSON 字符串时将抛出异常: JWTCreationException

当数据到期时数据验证将抛出异常: JWTVerificationException

当数据结构被破坏后数据验证将抛出异常: JWTDecodeException

当数据被篡改后数据验证将抛出异常: SignatureVerificationException