JWT token组成

JWT token的组成

JWT token由三个部分组成,头部(header)、有效载荷(payload)、签名(signature),
官网: https://jwt.io/

header部分由 typ 和 alg 组成,typ的全称是(type,类型)、alg全称(algorithm,算法),类型可以自己定义,没有限制。而alg: HS256,表示当前的token是使用HS256算法来进行加密的。HS256实际上是一种签名算法。
首先我们要了解几个名词:

  • 数字签名,数字签名和我们平常在文件中签上自己的名字是一样的,数字签名是为了防止伪造。
  • 数字摘要/数据指纹: 一般来说指的就是数据的hash值,比如SHA1/SHA256/SHA512/MD5等,这些都是常见的摘要算法,最简单的例子是我们在网上下载一个软件时,软件会有一个md5的编码,一般为了安全起见,
    都会让我们去验证下载下来的软件的md5和官方的md5是否匹配,如果匹配就表示没有被串改过
  • 加密算法,这个就比较容易理解了,就是直接对数据进行加密,加密算法和摘要算法最大的区别就是,加密是可逆的。常见的加密算法有对称加密和非对称加密等。
    数字签名一般的实现是,先对一个原始数据进行一次HASH摘要,然后再使用非对称加密算法(RSA、ECC等)对这个摘要进行加密,这样得到的结果就是原始数据的一个签名。
    那么用户在验证数据的时候,只需要使用公钥对签名进行解密,然后得到一组hash的摘要,用这个摘要和要比较的目标数据的摘要再进行比较,如果这两个摘要相等,说明验证成功,否则则验证失败。
    而在JWT中,提供了好几种签名算法的支持,分别是:
  • HS256, 这种签名算法是表示采用同一个[secret-key]进行签名与验证,这种就是属于对称加密的验证方式,一旦[secret_key]泄露,就无法保证安全性。
  • RS256,RS256采用的是RSA非对称加密算法来进行加密,使用公钥进行验证,通过私钥进行加密,公钥即使泄露也不会有影响,只需要确保私钥的安全即可。
  • ES256,ES256和RS256是一样的,都是使用私钥签名、公钥验证,算法速度上的差距也不大,但是ES算法的长度相对来说要短一些。

对于单体应用来说,HS256和RS256的安全性相差不大,如果是在微服务架构中,需要多方验证的场景,使用RS256/ES256的安全性会更高。

Header部分的数据,是通过base64位进行编码

base64编码 http://tool.oschina.net/encrypt?type=3 eyAKInR5cCI6ICJKV1QiLCAKImFsZyI6ICJIUzI1NiIKfSAK

payLoad

Payload 里面是 Token 的具体内容,也是一个json字符串,这些内容里面有一些是标准字段,你也可以添加其它需要的内容;payload的json结构并不像header那么简单,payload用来承载要传递的数据,
它的json结构实际上是对JWT要传递的数据的一组声明,这些声明被JWT标准称为claims , JWT默认提供了一些标准的Claim,具体内容如下。

  • iss(Issuser):代表这个JWT的签发主体;
  • sub(Subject):代表这个JWT的主体,即它的所有人;
  • aud(Audience):代表这个JWT的接收对象;
  • exp(Expiration time):是一个时间戳,代表这个JWT的过期时间;
  • nbf(Not Before):是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的;
  • iat(Issued at):是一个时间戳,代表这个JWT的签发时间;
  • jti(JWT ID):是JWT的唯一标识。

按照JWT标准的说明:标准的claims都是可选的,在生成playload不强制用上面的那些claim,你可以完全按照自己的想法来定义payload的结构,不过这样做根本没必要:

  • 第一是,如果把JWT用于认证, 那么JWT标准内规定的几个claim就足够用了,甚至只需要其中一两个就可以了,假如想往JWT里多存一些用户业务信息,比如角色和用户名等,这倒是用自定义的claim来添加;
  • 第二是,JWT标准里面针对它自己规定的claim都提供了有详细的验证规则描述,每个实现库都会参照这个描述来提供JWT的验证实现,所以如果是自定义的claim名称,那么你用到的实现库就不会主动去验证这些claim。
    同样,payLoad中的数据,也是拼接好之后,通过base64进行编码,得到一个目标字符串。

signature

signature表示签名,它的组成是。

signature=HS256(base64(header)+"."+base64(payload),secret_key)

签名的组成是,把header、payload分别通过base64进行编码,然后拼接在一起,使用 . 作为分隔符。

再通过header中声明的签名方法进行整体签名,其中HS256是一种对称加密方法,需要指定一个secret_key。最终得到的signature就成为了jwt中的第三个部分。

最后将这3个部分组成一个完整的字符串构成了JWT:base64(header)+”.”+base64(payload)+”.”+sinature 。 这就是JWT的核心。

secret_key是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它在任何场景都不应该流露出去。一旦客户端得知这个secret_key, 那就意味着客户端是可以自我签发jwt了

posted @ 2020-12-15 20:30  snail灬  阅读(3766)  评论(0编辑  收藏  举报