JWT加密解密
JWT (JSON Web Token) 是一种用于在各方之间安全地传输信息的紧凑、自包含的令牌。它由 三个部分 组成:Header、Payload 和 Signature,它们使用 .
分隔,如下所示:
header.payload.signature
1. JWT 的构成
Header(头部)
Header 包含两个主要部分:
- 类型:
typ
,即声明这是一个 JWT。 - 签名算法:
alg
,例如 HMAC、RSA 等。
示例:
json复制代码{"alg": "HS256","typ": "JWT"
}
编码(Base64Url 编码)后的 Header:
复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload(负载)
Payload 包含声明(Claims),即要传输的数据信息。声明可以是标准的注册声明,也可以是自定义的声明。
示例:
{"aud": "123", // 用户ID"info": "example_info", // 自定义信息"exp": 1728788687 // 过期时间 (UNIX时间戳)
}
编码后的 Payload:
复制代码
eyJhdWQiOiIxMjMiLCJpbmZvIjoiZXhhbXBsZV9pbmZvIiwiZXhwIjoxNzI4Nzg4Njg3fQ
Signature(签名)
Signature 是将 Header 和 Payload 编码后,通过签名算法(如 HMAC SHA256)以及密钥(secret
)生成的。
生成签名的过程:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret
)
假设密钥为 mysecret
,生成的 Signature 会是:
复制代码
3zkrxI4OSQztHk9H0O1DsX9hwppCu3lIjGt7E4jA8To
最终的 JWT 是:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjMiLCJpbmZvIjoiZXhhbXBsZV9pbmZvIiwiZXhwIjoxNzI4Nzg4Njg3fQ.3zkrxI4OSQztHk9H0O1DsX9hwppCu3lIjGt7E4jA8To
2. JWT 的加密和解密流程
加密(生成 Token)流程:
- Header 和 Payload 的编码:将 Header 和 Payload 转换为 JSON 字符串,并使用 Base64Url 编码。
- 生成签名:使用
base64UrlEncode(header) + "." + base64UrlEncode(payload)
,结合密钥和签名算法,生成签名。 - 拼接 Token:将 Header、Payload 和 Signature 拼接起来,构成完整的 JWT Token。
解密(验证 Token)流程:
- 提取 Header 和 Payload:从 JWT 中分离出 Header 和 Payload 并解码。
- 重新计算签名:使用 JWT 中的 Header 和 Payload,按照与生成签名时相同的方式重新计算签名。
- 校验签名:将重新计算的签名与 JWT 中的签名部分进行比较。如果相同,表示数据未被篡改;如果不同,表示数据已被篡改。
3. 如何确保 JWT 没有被篡改?
- 当 JWT 被生成后,其签名是基于 Header、Payload 和 密钥 共同生成的。
- 每次验证 JWT 时,服务器会使用与生成时相同的密钥,重新计算签名,并与 Token 中的签名进行比较。如果两者匹配,说明 Token 的数据没有被修改。
例如,如果有人修改了 JWT 的 Payload
部分(如用户 ID),签名的校验就会失败,因为修改后的 Payload 和原始密钥生成的签名不会匹配 JWT 中已有的签名。
举例说明:
-
假设我们生成了一个 JWT,内容如下:
复制代码 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjMiLCJpbmZvIjoiZXhhbXBsZV9pbmZvIiwiZXhwIjoxNzI4Nzg4Njg3fQ.3zkrxI4OSQztHk9H0O1DsX9hwppCu3lIjGt7E4jA8To
-
现在我们试图篡改 Payload,将
aud
从123
改为456
。篡改后的 JWT:复制代码 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI0NTYiLCJpbmZvIjoiZXhhbXBsZV9pbmZvIiwiZXhwIjoxNzI4Nzg4Njg3fQ.3zkrxI4OSQztHk9H0O1DsX9hwppCu3lIjGt7E4jA8To
-
当服务器验证时,会用新的 Payload 重新计算签名。由于 Payload 改变了,重新计算的签名将不会与原签名匹配,因此验证失败,说明 Token 被篡改。
4. 什么情况下会被判定为篡改?
- Payload 或 Header 被修改:如前述示例所示,如果篡改了 JWT 的 Payload(用户信息、自定义数据等),重新计算的签名将不匹配原始签名,验证失败。
- 使用不同的密钥:如果有人试图使用与原始密钥不同的密钥生成签名,验证时也会失败,因为解密时会使用正确的密钥进行校验。
总结
JWT 通过签名确保了 Token 的完整性,签名依赖于密钥和算法,因此只要签名匹配,便能确定 Token 未被篡改。如果 Token 的数据(Header 或 Payload)被篡改,签名将不匹配,校验失败,从而保障了 JWT 的安全性。