什么是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
Header 部分包含了 JWT 的类型(JWT)、加密算法(如 HMAC SHA256 或 RSA)、以及签名(如 HMAC SHA256 或 RSA 签名)。
1 | { |
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 | { |
Payload 部分默认是不加密的,建议不要在其中存储敏感信息。
Signature
Signature 部分由 Header 和 Payload 组合生成的签名,用于验证消息的完整性和身份。
签名的计算公式为:
1 | HMACSHA256( |
1 | SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
算出以上三个结果后,把 Header/Payload/Signature 三个部分用.连接起来就是完整的 JWT 字符串。
如何基于 JWT 实现用户认证?
- 用户注册:用户填写注册信息,服务器生成 JWT,并返回给用户。
- 用户登录:用户输入用户名和密码,服务器验证用户名和密码,生成 JWT,并返回给用户。
- 用户访问受保护资源:用户携带 JWT 访问受保护资源,服务器验证 JWT 有效性,并允许访问。
建议:
- JTW 存放在
localStorage
中,防止 CSRF 攻击。 - 常见做法是放在
HTTP Header
中,如Authorization: Bearer <JWT>
。
如何加强 JWT 的安全性?
JWT 包含了用户身份信息,如果被篡改,那么用户的身份就可能被伪造。
- 签名验证:服务器在生成 JWT 时,会把 Header、Payload、Signature 三个部分用.连接起来,然后用密钥生成签名。如果签名验证失败,则说明 JWT 被篡改。
- 有效期验证:服务器在生成 JWT 时,会设置一个有效期,如果 JWT 过期,则说明 JWT 被篡改。
- 黑名单验证:服务器可以维护一个黑名单,如果发现 JWT 被加入黑名单,则说明 JWT 被篡改。
JWT 安全的核心在于签名,签名的核心在于密钥。