跳到主要内容

JWT 签名和验证签名的过程

· 阅读需 3 分钟
素明诚
Full stack development

生成(签名)JWT

确定 Header:Header 通常包含两部分信息:使用的算法(比如 HS256 表示 HMAC SHA-256)和 Token 类型(通常是 JWT)。

{
"alg": "HS256",
"typ": "JWT"
}

构建 Payload:Payload 包含 claims,这些 claims 可以是注册的 claims、公共的 claims 或私有的 claims

{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

签名:使用 Header 中指定的算法和一个密钥对 Header 和 Payload 进行签名。签名的目的是验证 Token 在传输过程中未被篡改。

例如,如果使用 HMAC SHA-256,签名过程将是

  HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

组合 JWT:将编码后的 Header、Payload 和签名组合成一个 JWT。格式通常为header.payload.signature

JWT 验证过程

分解 JWT:首先,从 JWT 字符串中分离出 Base64 编码的 Header、Payload 和 Signature。JWT 通常形如header.payload.signature

Base64 解码:将编码的 Header 和 Payload 解码回它们原始的 JSON 格式的字符串。

重新生成签名:使用相同的算法(Header 中指定的,如 HMAC SHA-256)和secret对解码后的 Header 和 Payload 重新生成签名。具体步骤如下:

  1. 将解码后的 Header 和 Payload 重新转换成 Base64 编码的字符串。
  2. 将这两个 Base64 字符串用点.连接起来形成一个新的字符串。
  3. 使用secret作为密钥,对这个字符串进行 HMAC SHA-256 运算,生成新的签名。

比较签名:将重新生成的签名与 JWT 中原来包含的签名进行比较。如果两者相同,则认为 JWT 是有效的,没有被篡改,且是由掌握secret的实体发行的。

Secret 的作用

在这个验证过程中,secret起到的是保证签名真实性和数据未被篡改的关键角色:

  1. 签名的安全性:只有知道secret的实体才能正确生成和验证签名。这意味着即使有人截获了 JWT,但没有secret,他们也无法生成新的有效签名,从而无法伪造有效的 JWT。
  2. 数据的完整性:通过比较重新生成的签名和 JWT 中的签名,可以确认数据在传输过程中未被修改。因为任何对 Header 或 Payload 的改动都会导致新生成的签名与原签名不匹配。

检查 Claims:验证签名之后,还需要检查 Payload 中的 claims,如exp(过期时间)来确定 Token 的有效性。

注意

虽然 JWT 的 Header 和 Payload 是使用 Base64 编码的,这种编码是可逆的,因此任何人都可以看到内容。如果需要保密 Payload 中的数据,应考虑对 Payload 进行加密,这种情况下通常使用 JWE(JSON Web Encryption)。