JWT 的结构分析
JWT
数据组成:
- header
- payload
- 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
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