JSON Web Token (JWT) 是一个开放标准 (RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输 JSON 对象形式的信息。由于此信息是经过数字签名的,因此可以被验证和信任。JWT 是现代 Web 应用中 API 安全和身份验证的热门选择。
📋 目录
关键要点
- 结构:JWT由三部分组成:头部、载荷和签名,各部分之间用点分隔。
- 自包含:载荷包含有关用户的声明(例如,用户ID、角色),从而减少了数据库查找的需求。
- 安全性:签名用于验证令牌的完整性,确保其未被篡改。
- 无状态性:由于令牌是自包含的,JWT允许无状态身份验证,服务器无需存储会话状态。
- 常见用例:是API身份验证、微服务和各方之间安全信息交换的理想选择。
- 实现:在JavaScript、Python和Java等语言中广泛提供了用于创建和验证JWT的库,简化了集成。
准备好使用JWT了吗?我们的在线JWT解码器工具提供了一种简单的方法来解码、编码和检查您的令牌。您也可以使用我们的Base64编码工具处理Base64编码,或使用JSON格式化工具美化JWT载荷。
JWT的结构剖析
一个 JWT 由三个由点 (.) 分隔的部分组成:
| 部分 | 描述 |
|---|---|
| 头部 (Header) | 关于令牌的元数据。 |
| 载荷 (Payload) | 声明或数据。 |
| 签名 (Signature) | 用于验证令牌的完整性。 |
一个典型的 JWT 如下所示:xxxxx.yyyyy.zzzzz。
💡 快速提示: 使用我们的JWT解码工具可以立即查看JWT的三个部分及其内容。
头部(Header)
头部指定了令牌类型 (JWT) 和所使用的签名算法,例如 HMAC SHA256 或 RSA。
{
"alg": "HS256",
"typ": "JWT"
}
此 JSON 经过 Base64Url 编码 后形成 JWT 的第一部分。了解更多关于Base64编码原理。
载荷(Payload)
载荷包含声明 (claims),这些是关于一个实体(通常是用户)的陈述和附加数据。声明有三种类型:
- 注册声明 (Registered Claims):预定义的声明,如
iss(签发者)、exp(过期时间)、sub(主题) 和aud(受众)。建议使用这些声明以实现互操作性。 - 公共声明 (Public Claims):由开发者自定义的声明,应在 IANA JSON Web Token 注册表中注册以避免冲突。
- 私有声明 (Private Claims):为特定用例在各方之间创建的自定义声明,它们已同意其含义。
载荷示例:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
载荷也经过 Base64Url 编码 后形成 JWT 的第二部分。
⚠️ 安全警告: 载荷只是Base64编码,并非加密!任何人都可以解码查看内容。不要在载荷中存储敏感信息如密码或信用卡号。
签名(Signature)
签名是通过将编码后的头部、编码后的载荷、一个密钥和头部中指定的算法组合而成的。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your_secret_key
)
签名确保令牌未被篡改,并且在私钥签名的情况下,验证发件人的身份。了解更多关于哈希算法和MD5哈希。
多语言代码实现
JavaScript实现 (Node.js)
const jwt = require('jsonwebtoken');
// 编码 (签名)
const payload = { sub: '1234567890', name: 'John Doe' };
const secret = 'your-secret-key';
const token = jwt.sign(payload, secret, { expiresIn: '1h' });
// 解码 (验证)
const decoded = jwt.verify(token, secret);
📦 安装依赖:
npm install jsonwebtoken
Python实现
import jwt
# 编码
payload = {'sub': '1234567890', 'name': 'John Doe'}
secret = 'your-secret-key'
token = jwt.encode(payload, secret, algorithm='HS256')
# 解码
decoded = jwt.decode(token, secret, algorithms=['HS256'])
📦 安装依赖:
pip install pyjwt
Java实现
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
// 编码
String token = Jwts.builder()
.setSubject("1234567890")
.claim("name", "John Doe")
.signWith(SignatureAlgorithm.HS256, "your-secret-key".getBytes())
.compact();
// 解码
Claims claims = Jwts.parser()
.setSigningKey("your-secret-key".getBytes())
.parseClaimsJws(token)
.getBody();
📦 Maven依赖:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
JWT安全最佳实践
1. 密钥管理
- 使用强随机密钥(至少256位)
- 定期轮换密钥
- 使用环境变量存储密钥,不要硬编码
2. 令牌存储
- 优先使用
HttpOnlycookie存储 - 避免使用
localStorage(易受XSS攻击) - 在HTTPS上传输令牌
3. 过期时间设置
- 访问令牌:15分钟-1小时
- 刷新令牌:7-30天
- 实现刷新令牌机制
4. 载荷安全
- 不要存储敏感信息
- 最小化载荷大小
- 使用JWE加密敏感载荷
🔐 延伸阅读: 了解更多关于Bearer Token认证和API安全最佳实践。
常见问题解答
1. 我应该在客户端哪里存储JWT?
将JWT存储在HttpOnly cookie中以防止XSS攻击。避免使用localStorage或sessionStorage,因为它们容易受到脚本访问的攻击。使用我们的JWT解码工具可以快速检查JWT内容。
2. 如何处理JWT过期和令牌续订?
实现刷新令牌机制。当访问令牌过期时,使用一个长寿命的刷新令牌来请求新的访问令牌,而无需用户重新登录。推荐访问令牌有效期15-60分钟,刷新令牌7-30天。
3. JWT、JWS和JWE有什么区别?
- JWT是标准(RFC 7519)
- **JWS (JSON Web Signature)**是签名的JWT,确保完整性
- **JWE (JSON Web Encryption)**是加密的JWT,确保机密性
大多数情况下使用的是JWS。
4. JWT是加密方法吗?
不,标准的JWS是签名的,而不是加密的。任何截获令牌的人都可以看到有效载荷。如果需要加密有效载荷,请使用JWE。了解更多关于Base64编码和加密的区别。
5. JWT令牌多大合适?
建议控制在1KB以内。过大的JWT会增加网络传输开销和cookie大小限制问题。只在载荷中包含必要的声明。
6. 如何撤销JWT?
JWT本身是无状态的,无法直接撤销。常见方案:
- 维护令牌黑名单
- 缩短过期时间
- 使用刷新令牌机制
- 版本化令牌(在载荷中添加版本号)
总结
JWT 为现代应用中的身份验证和信息交换提供了强大而灵活的解决方案。通过了解其结构、流程和安全考量,您可以构建安全、可扩展和无状态的系统。
关键要点回顾
✅ JWT由头部、载荷、签名三部分组成
✅ 使用Base64Url编码,非加密
✅ 适合无状态API认证
✅ 必须使用HTTPS传输
✅ 合理设置过期时间和刷新机制
相关工具推荐
- JWT在线解码器工具 - 快速解码和验证JWT
- Base64编码解码工具 - 处理Base64编码
- JSON格式化工具 - 美化JSON载荷
- URL编码工具 - URL安全编码
延伸阅读
💡 开始使用: 访问我们的编解码工具分类页探索更多安全工具!