首页 > 解决方案 > 为什么在 JWT Token 中包含 Header 和 Payload?

问题描述

我确定我在这里遗漏了一些非常简单的东西,但我刚开始学习 JWT 令牌进行身份验证,据我所知,JWT 令牌的结构是:

Base64UrlEncode(Header) + '.' +  Base64UrlEncode(Payload) + '.' + CreateSignature(Header, Payload, Secret_Key)

我的理解是您将其发送给客户端,它允许客户端在需要时将其发送回服务器。此时您解密签名以确保它没有被您的私钥篡改。

我感到困惑的部分是为什么您需要将第一部分Base64UrlEncode(Header) + '.' + Base64UrlEncode(Payload) + '.'轻松转换回纯文本,然后呢?

由于您将在服务器上对其进行解密,因此您不能只传递签名,使用您的密钥解密并读取有效负载,而其他人则不能吗?

看起来这会更安全,因为第一部分可以很容易地转换回纯文本,并为攻击者提供存储在有效负载中的信息,例如token expiration,等。userId

我错过了什么?

标签: securityauthenticationjwtaccess-token

解决方案


签名不包含有效负载。签名可以像 jwt 的哈希 (SHA256) 的消息验证码 (HMAC) 一样简单。因此,如果您只发送签名,那将作为一个普通的旧会话 id 工作,并且服务器仍然必须存储状态,从而否定 jwt 的任何好处。

不过你是对的,默认情况下 jwt 是不加密的。虽然使用 base64 编码,但从安全角度来看,它只是纯文本,不应包含敏感(秘密)信息。签名提供的唯一保护是,当服务器接收到它时,它可以通过检查签名来确保 jwt 中的信息在客户端上没有被更改。

未加密的令牌允许客户端检查其内容并找出例如到期时间、何时必须获取新令牌或登录用户的 ID。拥有 jwt 的用户无论如何都会拥有这种信息,而其他人不应该拥有 jwt,因为他们可以使用它进行身份验证来冒充用户。

但是,在特殊情况下,您可能仍希望包含您希望在服务器上接收回但又不想透露给客户端的敏感信息(即秘密)。为此,您可以使用加密的 jwt (jwe)。缺点是这个令牌对客户端来说是不透明的,您可能必须实现应用程序端点来检索所有必要的信息。


推荐阅读