- 2019-11-17
Json Web Token解析
介绍
JWT(JSON Web Token) 是一个开放标准(RFC7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
注意:JWT包含了两种实现JWE和JWS,通常我们说的JWT其实是JWS。
结构
JWS
1.组成
JWS由三部分组成,它们之间用圆点(.)连接。这三部分分别是:
- Header
- Payload
- Signautre
2.Header
jwt的头部通常由两部分信息组成:
- type (声明类型,默认值JWT,typ元素用于定义完整JWT的媒体类型。媒体类型是一种标识符,它定义了在Internet上传输的内容的格式。更多媒体类型请参考这里:media-types)
- alg (声明加密的算法,常用的有hmac、sha256,默认值HS256,更多算法请参考algorithms)
- kid (某些jwt含有此header,这个表示jwt的秘钥id,用来验证jwt是否有效,一个秘钥id对应一个key,通过key来验证。例如Google oauth2认证的id_token里就含有kid)
其他更多header保留字段请参考这里:Registered Header Parameter Names
{
"alg": "HS256",
"typ": "JWT"
}
对上面的部分进行base64编码,会得到一个字符串:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,这就是JWS的header。
3.Payload
Payload就是存放有效信息的地方,它包含声明(要求)。声明有三种类型:
-
registered claims:标准中注册的声明。这里有一组预定义的声明,它们不是强制的,但是推荐用。
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的
- iat: jwt的签发时间
- jti: jwt的唯一标识
更多保留声明请看这里:claims
-
public claims:公共的声明
- 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
-
private claims:私有的声明
- 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是可以反编码的,意味着该部分信息可以归类为明文信息。
例如google-sign-in-oauth里的例子:
{
"sub": 1234567890, // The unique ID of the user's Google Account
"iss": "https://accounts.google.com", // The assertion's issuer
"aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
"iat": 233366400, // Unix timestamp of the assertion's creation time
"exp": 233370000, // Unix timestamp of the assertion's expiration time
"name": "Jan Jansen",
"given_name": "Jan",
"family_name": "Jansen",
"email": "jan@gmail.com", // If present, the user's email address
"locale": "en_US"
}
base64编码后得到:
eyJzdWIiOjEyMzQ1Njc4OTAsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbSIsImF1ZCI6IjEyMy1hYmMuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJpYXQiOjIzMzM2NjQwMCwiZXhwIjoyMzMzNzAwMDAsIm5hbWUiOiJKYW4gSmFuc2VuIiwiZ2l2ZW5fbmFtZSI6IkphbiIsImZhbWlseV9uYW1lIjoiSmFuc2VuIiwiZW1haWwiOiJqYW5AZ21haWwuY29tIiwibG9jYWxlIjoiZW5fVVMifQ
4.Signature
JWT的第三部分是一个签名信息,这个签名信息由三部分组成:
- header (base64后的)
- payload (base64后的)
- secret
第三部分需要base64编码后的header和base64编码后的payload使用 . 连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了JWT的第三部分。
这里通过jwt官网来得到secret:https://jwt.io,设置加密secret为test,进行base64编码得到第三部分signature如下:
I4hrpo7eEAiYNQaQTnvSVZy7cq0PMq8DwVUmam6927A
注意:
secret是保存在服务器端的,JWT的签发生成也是在服务器端的,secret就是用来进行JWT的签发和JWT的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发JWT了。
5.优缺点
优点:轻量、简单,保证JWT不被串改,通常用于认证。
缺点:不够安全,即claim可以解开看到明文信息,所以不能放入敏感数据。
JWE
1.组成
JWE由五部分组成:
- JOSE Header
- JWE Encrypted Key
- JWE Initialization Vector
- JWE Ciphertext
- JWE Authentication Tag
2.生成JWE的步骤:
- 生成随机内容加密密钥(CEK)。
- 使用RSAES-OAEP 加密算法,用接收人的公钥加密CEK,生成JWE加密密钥。
- 对JWE加密的密钥进行base64url编码。
- 生成一个随机的JWE初始化向量。
- 对JWE初始化向量进行base64urls编码。
- 让额外的经过身份验证的数据加密参数为ASCIl(BASE64URL(UTF8(JWE Protected Header)))
- 使用AES GCM加密算法对明文部分进行加密生成密文Ciphertext,算法会随之生成一个128位的认证标记Authentication Tag。
- 对密文进行base64urls编码。
- 对Authentication Tag进行base64urls编码
3.优缺点
优点:安全可靠,通常用于数据传输。
缺点:不够轻量,有点复杂。
- 上一篇: Golang MongoDB扩展包之高级特性
- 下一篇: Mac搭建kubernetes集群之环境准备
评论一下