什么是JWT?

什么是 JWT?

JWT(JSON Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息。该信息可以是声明(claim)、有效期、签名或密钥。JWT 可以使用 HMAC 算法或 RSA 算法进行签名。

JWT 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。

可以看出,JWT 更符合设计 RESTful API 时的「Stateless(无状态)」原则 。

JWT 拆分

JWT 本质上就是一组字串,通过(.)切分成三个为 Base64 编码的部分:

  • Header(头部):包含 JWT 的类型(JWT)、加密算法(如 HMAC SHA256 或 RSA)、以及签名(如 HMAC SHA256 或 RSA 签名)。
  • Payload(负载):包含声明(claim)、有效期、以及其他一些信息。
  • Signature(签名):由 Header 和 Payload 组合生成的签名,用于验证消息的完整性和身份。
1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

你可以在 jwt.io 这个网站上对 JWT 进行解码,解码之后得到的就是 Header、Payload、Signature 这三部分。

Header 和 Payload 都是 JSON 格式的数据,Signature 由 Payload、Header 和 Secret(密钥)通过特定的计算公式和加密算法得到。

Header 部分包含了 JWT 的类型(JWT)、加密算法(如 HMAC SHA256 或 RSA)、以及签名(如 HMAC SHA256 或 RSA 签名)。

1
2
3
4
{
"typ": "JWT",
"alg": "HS256"
}

typ 字段表示 JWT 类型,alg 字段表示加密算法。

Payload

Payload 部分包含声明(claim)、有效期、以及其他一些信息。声明是关于用户身份和其他属性的声明,有效期是声明的生效时间和失效时间。

claims 分为三种类型:

  • Registered claims:这些是预定义的声明,一般情况下,这些声明都是可选的,但建议使用。
  • Public claims:这些声明是公开的,任何人都可以定义。
  • Private claims:这些声明是私有的,只能在特定的场景下使用。

一些常见的声明:

  • iss(issuer):签发人
  • sub(subject):主题
  • aud(audience):受众
  • exp(expiration time):过期时间
  • nbf(not before):生效时间
  • iat(issued at):签发时间
  • jti(JWT ID):JWT 唯一标识符
1
2
3
4
5
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

Payload 部分默认是不加密的,建议不要在其中存储敏感信息。

Signature

Signature 部分由 Header 和 Payload 组合生成的签名,用于验证消息的完整性和身份。

签名的计算公式为:

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
<SECRET_KEY>)
1
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

算出以上三个结果后,把 Header/Payload/Signature 三个部分用.连接起来就是完整的 JWT 字符串。

如何基于 JWT 实现用户认证?

  1. 用户注册:用户填写注册信息,服务器生成 JWT,并返回给用户。
  2. 用户登录:用户输入用户名和密码,服务器验证用户名和密码,生成 JWT,并返回给用户。
  3. 用户访问受保护资源:用户携带 JWT 访问受保护资源,服务器验证 JWT 有效性,并允许访问。

建议:

  1. JTW 存放在 localStorage 中,防止 CSRF 攻击。
  2. 常见做法是放在HTTP Header中,如Authorization: Bearer <JWT>

如何加强 JWT 的安全性?

JWT 包含了用户身份信息,如果被篡改,那么用户的身份就可能被伪造。

  • 签名验证:服务器在生成 JWT 时,会把 Header、Payload、Signature 三个部分用.连接起来,然后用密钥生成签名。如果签名验证失败,则说明 JWT 被篡改。
  • 有效期验证:服务器在生成 JWT 时,会设置一个有效期,如果 JWT 过期,则说明 JWT 被篡改。
  • 黑名单验证:服务器可以维护一个黑名单,如果发现 JWT 被加入黑名单,则说明 JWT 被篡改。

JWT 安全的核心在于签名,签名的核心在于密钥。