在今天的数字化世界中,安全地传递信息变得越来越重要。JSON Web Token
(JWT
)作为一种流行的开放标准,为简化服务器与客户端之间的安全交流提供了一种高效的方式。本文旨在深入解析JWT
的工作原理,并通过示例演示如何使用JWT
进行安全通信。我们将从JWT
的基本组成部分讲起,探讨公密钥加密的原理,解释为什么JWT
是安全的,以及如何验证JWT
的有效性。
一、JWT介绍
1. JWT组成部分
JWT由三个部分组成,它们分别是头部(Header)、载荷(Payload)、和签名(Signature)。通过将这三部分用点(.
)连接起来,形成了一个完整的JWT字符串。例如:xxxxx.yyyyy.zzzzz
。
2. 头部(Header)
头部通常由两部分组成:令牌类型(typ
)和签名算法(alg
)。例如:
1 | { |
kid (Key ID)
:密钥标识符,用于指明验证JWT签名时使用的密钥。在含有多个密钥的系统中,这可以帮助接收者选择正确的密钥进行验证。这里的值33bd1cad-62a6-4415-89a6-c2c816f3d3b1是一个UUID,唯一标识了用于签名的密钥。alg (Algorithm)
:指明用于签名的算法,这里是RS256,表示使用RSA签名算法和SHA-256散列算法。这种算法属于公钥/私钥算法,意味着使用私钥进行签名,而用公钥进行验证。
3. 载荷(Payload)
载荷包含了所要传递的信息,这些信息以声明(claims)的形式存在。声明可以是用户的身份标识,也可以是其他任何必要的信息。载荷示例:
1 | { |
sub (Subject)
:主题,标识了这个JWT的主体,通常是指用户的唯一标识。这里XcWebApp可能是一个应用或用户标识。aud (Audience)
:受众,标识了这个JWT的预期接收者。这里同样是XcWebApp,意味着这个JWT是为XcWebApp这个应用或服务生成的。nbf (Not Before)
:生效时间,这个时间之前,JWT不应被接受处理。这里的时间是Unix时间戳格式,表示JWT生效的具体时间。iss (Issuer)
:发行者,标识了这个JWT的发行方。这里是http://localhost:63070/auth,表明JWT由本地的某个认证服务器发行。exp (Expiration Time)
:过期时间,这个时间之后,JWT不再有效。同样是Unix时间戳格式,表示JWT过期的具体时间。iat (Issued At)
:发行时间,JWT创建的时间。这提供了JWT的时间信息,也是Unix时间戳格式。jti (JWT ID)
:JWT的唯一标识符,用于防止JWT被重放(即两次使用同一个JWT)。这里的值是一个UUID,确保了JWT的唯一性。
4. 签名(Signature)
签名是对头部和载荷的加密保护,确保它们在传输过程中未被篡改。根据头部中指定的算法(例如HS256),使用私钥
对头部和载荷进行签名。
二、深入理解JWT签名验证
1. 签名生成
- 哈希处理 :首先对JWT的
头部和载荷
部分(经过Base64编码并用.连接的字符串)进行哈希处理,生成一个哈希值。这个步骤是为了确保数据的完整性,即使是微小的改动也会导致哈希值有很大的不同。 - 私钥加密哈希值 :然后使用发行者的
私钥
对这个哈希值
进行加密,生成的结果就是JWT的签名部分。这个加密的哈希值(签名)附加在JWT的后面。
2. 签名验证
- 哈希处理 :接收方收到JWT后,会独立地对其头部和载荷部分进行
同样的哈希
处理,生成一个哈希值。 - 公钥解密签名 :接收方使用发行者的
公钥
对签名(加密的哈希值)进行解密
,得到另一个哈希值。 - 哈希值比较 :
比较这两个哈希值
。如果它们相同,就证明了JWT在传输过程中未被篡改,因为只有相应的私钥能够生成一个对应的、能够通过公钥解密并得到原始哈希值的签名。
3. 为什么JWT是安全的
由于破解RSA算法的难度极高,没有私钥就无法生成有效的签名,因此无法伪造签名。这就是为什么使用公钥进行签名验证是安全的原因。
三、如何验证JWT是否有效
对于一个JWT,我们可以使用Base64解码,获取前两部分信息,可以进行token是否过期
等验证,具体取决于前两部分具体内容,这是可以人为设置的。
对于签名部分,可以用公钥去验证其有效
性(即是否被纂改)。
四、 Why JWT?
为什么是JWT?
首先是不可伪造的安全性
,其次,因为你会发现,只要有公钥就可以验证JWT这种token,这也就意味着对于微服务来说,任意微服务都有能力自行验证JWT,而不需要额外的验证模块。这种自校验没有用到网络通信,性能十分好
。同时,JWT有时间限制
,一定程度上也提高了最坏情况的安全性。