JWT格式
由header、payload、signature三部分组成,中间用圆点(.)连接:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpYW0uYXBpLm1hcm1vdGVkdS5jb20iLCJleHAiOjE2NDI4NTY2MzcsImlkZW50aXR5IjoiYWRtaW4iLCJpc3MiOiJpYW0tYXBpc2VydmVyIiwib3JpZ19pYXQiOjE2MzUwODA2MzcsInN1YiI6ImFkbWluIn0.Shw27RKENE_2MVBq7-c8OmgYdF92UmdwS8xE-Fts2FM
JWT中,每部分包含的信息如下:
Header
包含类型和加密算法,如
{
"typ": "JWT", // 类型为JWT
"alg": "HS256" // 加密算法,这里是 HS256(alg 算法可以有多种)
}
在某些场景下,可能还会有 kid 选项,用来标识一个密钥 ID,例如:
{
"alg": "HS256",
"kid": "XhbY3aCrfjdYcP1OFJRu9xcno8JzSbUIvGE2",
"typ": "JWT"
}
将Header进行base64编码:
$ echo -n '{"typ":"JWT","alg":"HS256"}'|base64
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
Payload
Payload 中携带 Token 的具体内容, 由三部分组成:JWT 标准中注册的声明(可选)、公共声明、私有声明。
JWT 标准中注册的声明部分,有以下标准字段:
本例中的 payload 内容为:
{
"aud": "iam.authz.marmotedu.com", // 接收方
“exp”: 1604158987, // 过期时间
“iat”: 1604151787, // 签发时间
“iss”: "iamctl", // 签发者
“nbf": 1604151787 // 生效时间
}
同样将将 Payload 进行 base64 编码:
$ echo -n '{"aud":"iam.authz.marmotedu.com","exp":1604158987,"iat":1604151787,"iss":"iamctl","nbf":1604151787}'|base64
eyJhdWQiOiJpYW0uYXV0aHoubWFybW90ZWR1LmNvbSIsImV4cCI6MTYwNDE1ODk4NywiaWF0Ijox
NjA0MTUxNzg3LCJpc3MiOiJpYW1jdGwiLCJuYmYiOjE2MDQxNTE3ODd9
除此之外,还有公共的声明和私有的声明。公共的声明可以添加任何的需要的信息,一般添加用户的相关信息或其他业务需要的信息,注意不要添加敏感信息;私有声明是客户端和服务端所共同定义的声明,因为 base64 是对称解密的,所以一般不建议存放敏感信息。
Signature
将 Header 和 Payload 分别 base64 编码后,用 . 连接, 然后使用Header中加密方式,利用 secretKey 对连接后的字符串进行加密,加密后的字符串即为最终的 Signature。
secretKey 是密钥,保存在服务器中,一般通过配置文件来保存,例如:
最后生成的 Token 如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJpYW0uYXV0aHoubWFybW90ZWR1LmNvbSIsImV4cCI6MTYwNDE1ODk4NywiaWF0IjoxNjA0MTUxNzg3LCJpc3MiOiJpYW1jdGwiLCJuYmYiOjE2MDQxNTE3ODd9.LjxrK9DuAwAzUD8-9v43NzWBN7HXsSLfebw92DKd1JQ
签名后服务端会返回生成的 Token,客户端下次请求会携带该 Token。
服务端收到 Token 后会解析出 header和payload,然后用相同的加密算法和密钥再次计算Signature,和收到的Signature相比较,相同则认证通过。
(因此服务端无需保存token,收到后重新计算即可验证是否合法)