Json Web Token解析

胡大大 2020-09-17 14:20:13 1076 0 comments

介绍

JWT(JSON Web Token) 是一个开放标准(RFC7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
注意:JWT包含了两种实现JWEJWS,通常我们说的JWT其实是JWS。

96B541C816C345E398A2F2A1F17E5DC1.png

结构

JWS

1.组成

JWS由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

  • Header
  • Payload
  • Signautre

8A9BF77A4F7447F68024547B053B9929.png

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

B236EC58CBE44681B06692F75B71D56B.png

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.优缺点

优点:安全可靠,通常用于数据传输。

缺点:不够轻量,有点复杂。



标签
web
评论一下

评论列表

暂时没有评论,快来评论吧..