JWT,全称为JSON Web Token,是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方法,用于在各方之间以JSON对象的形式安全地传输信息。这些信息可以被验证和信任,因为它们是数字签名的。JWT的主要用途包括身份验证、信息交换和授权。
文章目录
- 1 一、JWT的结构
- 1.1 Header(头部):
- 1.2 Payload(负载):
- 1.3 Signature(签名):
- 1.4 JWT示例
- 2 二、如何使用JWT?
- 3 三、JWT的应用场景
- 4 四、安全性考虑
- 4.1 密钥管理
- 4.2 过期时间
- 4.3 签名算法
- 4.4 HTTPS
- 4.5 限制JWT权限
- 4.6 防止重放攻击
- 4.7 正确的JWT解析
一、JWT的结构
一个JWT由三部分组成,每部分使用点(.)分隔:
Header(头部):
- 包含令牌的元数据,通常包括令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
```json
{
"alg": "HS256",
"typ": "JWT"
}
```
Payload(负载):
- 包含声明(claims),声明是关于实体(通常是用户)和其他数据的断言。声明有三种类型:
- **Registered claims(注册声明)**:如iss(发行者)、exp(过期时间)、sub(主题)、aud(受众)等。
- **Public claims(公共声明)**:由标准组织定义,可以用于公开信息。
- **Private claims(私有声明)**:自定义的声明,通常用于双方之间的信息交换。
```json
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
```
Signature(签名):
- 用于验证消息的发送者以及消息的完整性。签名的生成过程如下:
- 取编码后的头部和负载,使用点(.)连接。
- 使用指定的签名算法和一个密钥(私钥或秘密密钥)进行签名。
```plaintext
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
```
JWT示例
一个JWT示例如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
二、如何使用JWT?
生成JWT
生成JWT通常包括以下步骤:
- 创建Header:
- 创建Payload:
- 生成Signature:
- 组合JWT:
- 将编码后的Header、Payload和Signature用点(.)连接:
plaintext eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
验证JWT
验证JWT的过程包括以下步骤:
- 分解JWT:
- 将JWT按点(.)分隔,得到Header、Payload和Signature。
- 验证Signature:
- 使用相同的签名算法和密钥对Header和Payload进行签名,并与接收到的Signature进行比较,以验证JWT的完整性和真实性。
- 验证声明:
- 检查Payload中的声明是否符合预期,例如检查exp(过期时间)是否有效。
三、JWT的应用场景
- 身份验证:
- JWT广泛用于用户身份验证。例如,在用户登录时,服务器生成一个JWT并返回给客户端。客户端随后在每个请求中附带此JWT,以证明其身份。服务器可以通过验证JWT来确保请求的合法性。
- 信息交换:
- JWT还可以用于在不同服务之间安全地传递信息。由于JWT是自包含的,它携带的信息可以被信任和验证,因此非常适合分布式系统中的数据传输。
- 授权:
- 在一些场景中,JWT可以携带用户权限信息,使得服务可以根据JWT中的声明决定是否授予特定操作的权限。
四、安全性考虑
虽然JWT在很多场景中非常有用,但使用时需要注意以下安全性问题,以确保系统的安全性和JWT的有效性:
密钥管理
- 密钥保密:用于签名JWT的密钥(例如HMAC中的秘密密钥或RSA的私钥)必须妥善保管,确保其不被泄露。密钥的泄露将导致任何人都能伪造JWT。
- 密钥轮换:定期更换签名密钥,以减少密钥被泄露或破解后的风险。确保在密钥轮换时可以平滑过渡,例如支持多密钥签名验证。
过期时间
- 设置合理的过期时间(exp):确保JWT在一定时间后失效,减少长期有效令牌被滥用的风险。一般来说,过期时间应设置为几分钟到几小时之间。
- 即时吊销:在某些情况下,可能需要即时吊销某些JWT。虽然JWT本身不支持即时吊销,但可以结合黑名单机制,将需要吊销的JWT记录在黑名单中,每次验证JWT时检查是否在黑名单内。
签名算法
- 使用强加密算法:选择安全的签名算法,如HMAC SHA256或RSA。避免使用不安全或过时的算法,如HMAC SHA1。
- 避免算法攻击:在验证JWT时,不要信任从令牌头部获取的算法信息,而是使用预期的算法进行验证。防止攻击者修改头部中的算法字段以绕过安全验证。
HTTPS
- 通过HTTPS传输JWT:确保JWT通过HTTPS进行传输,以防止中间人攻击(MITM)。通过HTTPS加密传输数据,防止JWT在传输过程中被截获或篡改。
- 避免JWT在URL中传递:不要在URL参数中传递JWT,因为URL可能被记录在服务器日志、浏览器历史记录或其他不安全的位置。建议将JWT放在HTTP请求头部(如Authorization头部)中传递。
限制JWT权限
- 最小权限原则:在JWT中仅包含必要的权限和信息,避免将过多的敏感信息放入JWT中。确保JWT的权限范围(scope)最小化,以降低被滥用的风险。
- 多级权限控制:针对不同的应用场景,可以设计多级权限控制机制。例如,将用户的角色、权限信息放入JWT中,并在服务器端根据这些信息进行权限校验。
防止重放攻击
- 使用唯一标识(jti):在JWT中加入唯一标识(jti,JWT ID),并在服务器端存储已使用的JWT ID,确保每个JWT只能使用一次。
- 时间戳和滑动窗口:结合时间戳(iat,issued at)和滑动时间窗口机制,防止JWT在一段时间内被重复使用。确保在合理的时间窗口内,JWT只能使用一次。
正确的JWT解析
- 避免信息泄露:解析JWT时,确保对头部和负载部分进行适当的校验和解码。避免直接将解析后的信息暴露给用户,防止敏感信息泄露。
- 校验声明:在使用JWT中的声明前,确保对关键声明进行校验。例如,校验发行者(iss)、受众(aud)和过期时间(exp)等,确保JWT来源可信且未过期。
JWT是一种强大且灵活的工具,适用于身份验证、信息交换和授权。然而,在使用JWT时,必须注意上述安全性考虑,确保密钥的安全管理、合理的过期时间设置、使用强加密算法、通过HTTPS传输、限制JWT权限、防止重放攻击以及正确解析JWT等。通过这些措施,可以有效地提高系统的安全性和可靠性,防止JWT被滥用或攻击。