JWT(JSON Web Token)基础概念详解
一、JWT核心组成
JWT由三部分组成,用点号.
分隔:
-
Header(头部)
- 包含令牌类型(
typ
)和签名算法(alg
) - 示例:
{"alg":"HS256","typ":"JWT"}
- 会被Base64Url编码
- 包含令牌类型(
-
Payload(载荷)
- 存储实际声明(Claims),分为三类:
- 注册声明:标准字段(如
iss
发行者、exp
过期时间) - 公共声明:自定义但公开的字段(如
user_id
) - 私有声明:应用自定义的私有字段
- 注册声明:标准字段(如
- 示例:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
- 会被Base64Url编码
- 存储实际声明(Claims),分为三类:
-
Signature(签名)
- 用于验证令牌完整性和真实性
- 生成方式:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
- 示例(使用HS256算法和密钥
secret
)
二、JWT工作流程
-
客户端登录
- 用户提交凭证(如用户名密码)
- 服务端验证成功后生成JWT返回给客户端
-
客户端存储JWT
- 通常存储在
localStorage
或Cookie
中(注意XSS/Cookie安全配置)
- 通常存储在
-
后续请求携带JWT
- 客户端在HTTP请求头中添加:
Authorization: Bearer <JWT_TOKEN>
- 或通过Cookie发送(需设置
HttpOnly
和Secure
)
- 客户端在HTTP请求头中添加:
-
服务端验证JWT
- 解码Header和Payload(无需查询数据库)
- 验证签名是否合法
- 检查过期时间(
exp
)等声明
三、JWT关键特性
-
无状态性
- 服务端不需要存储会话信息,适合分布式系统
-
自包含性
- 所有必要信息都在令牌中(如用户ID、角色)
-
跨域支持
- 天然支持跨域请求(相比Session+Cookie方案)
-
防篡改
- 签名机制确保令牌内容不可被修改
四、JWT常见声明(Claims)
声明类型 | 示例 | 说明 |
---|---|---|
注册声明 | iss (发行者)、exp (过期时间) | 标准字段,有特定含义 |
公共声明 | user_id 、role | 自定义但公开的字段 |
私有声明 | company_id | 应用自定义的私有字段 |
五、JWT使用场景
-
身份认证
- 替代传统Session方案(如RESTful API认证)
-
单点登录(SSO)
- 多系统共享同一JWT实现无缝登录
-
信息交换
- 安全地在各方之间传递信息(如微服务间通信)
六、JWT安全注意事项
-
密钥保护
- 使用强密钥(至少256位),不要硬编码在代码中
-
过期时间设置
- 必须设置合理的
exp
(建议不超过1小时) - 可配合
refresh_token
机制实现长期会话
- 必须设置合理的
-
敏感信息避免存储
- 不要在Payload中存储密码等敏感信息(JWT可被解码)
-
HTTPS传输
- 必须使用HTTPS防止令牌被截获
-
防止令牌泄露
- 前端存储时注意XSS防护(避免
localStorage
存储敏感令牌) - 考虑使用
HttpOnly
Cookie存储(但会失去无状态优势)
- 前端存储时注意XSS防护(避免
七、JWT与Session对比
特性 | JWT | Session |
---|---|---|
存储位置 | 客户端 | 服务端 |
状态管理 | 无状态 | 有状态 |
扩展性 | 高(适合分布式) | 低(需共享Session) |
安全性 | 依赖密钥和传输安全 | 依赖Session管理 |
适用场景 | API认证、微服务 | 传统Web应用 |
八、典型JWT示例
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
// Signature(使用HS256算法和密钥"secret"生成)
// 最终JWT:xxxxx.yyyyy.zzzzz
九、JWT生成与验证(代码示例)
// 使用Java生成JWT(jjwt库)
String jwt = Jwts.builder()
.setSubject("1234567890")
.claim("name", "John Doe")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时后过期
.signWith(SignatureAlgorithm.HS256, "secret".getBytes())
.compact();
// 验证JWT
Claims claims = Jwts.parser()
.setSigningKey("secret".getBytes())
.parseClaimsJws(jwt)
.getBody();
十、总结
- JWT是无状态的身份认证方案,适合现代分布式系统
- 核心优势:无状态、跨域支持、自包含
- 关键安全措施:强密钥、合理过期时间、HTTPS传输
- 适用场景:API认证、微服务、单点登录
- 注意事项:避免存储敏感信息,注意令牌泄露风险