JWT(JSON Web Token)
是一种基于JSON的开放标准(RFC 75419),用于在网络应用间安全地传递声明信息.它通过数字签名保证信息的完整性和真实性,常被用来用于身份验证,信息交换等场景.
JWT即是令牌技术,是用于用户在登录后确认用户的身份,并且无需频繁查询数据库来确认用户身份.JWT是由三部分组成,用'.'分隔,分别为:头部,载荷,签名.
头部
头部包含两个字段:
- alg:使用签名的算法(如 HS256, RS256等)
- typ:令牌类型,固定为JWT
载荷
存储需要传递的声明信息,分为三类:
- 注册声明:预定义的标准字段(可选),如
iss(签发者)、exp(过期时间)、sub(主题)、aud(受众)等. - 公共声明:自定义字段,需避免冲突(通常使用 URI 作为命名空间).
- 私有声明:双方约定的自定义字段,用于传递业务信息.
签名
由Base64将头部,载荷,密钥转换成的字符串
JWT的工作流程
- 用户登录:客户端提交账号密码等信息到服务器
- 生成 JWT:服务器验证通过后,生成包含用户信息和过期时间的 JWT,返回给客户端。
- 客户端存储:客户端将 JWT 保存在 localStorage、sessionStorage 或 Cookie 中。
- 后续请求:客户端每次请求时,在 HTTP 头部(如
Authorization: Bearer <token>)携带 JWT。 - 服务器认证: 服务器解析 JWT,验证签名和过期时间,确认有效后处理请求。
代码实现
//JWT签名密钥,使用Base64编码
private static String signKey="SVRIRULNQQ==";
//过期时间,设置为12小时
private static Long expire=12 * 60 *60 *1000;
/**
* 生成JWT令牌
* @return
*/
public static STring generateJwt(Map<String , Object> claims){
String jwt =Jwts.builder().
addClaims(claims).
signWith(SignatureAlgorithm.HS256, signKey).
setExpiration(new Data(System.CurrentTimeMillis()+expire)).
compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims.claims =Jwts.parser().
setSigningKey(sinKey).
parseClaimsJws(jwt).
getBody();
return Claims;
}
JWT 的优缺点
优点:
- 无状态:服务器无需存储会话信息,减轻服务器负担,适合分布式系统。
- 自包含:Payload 包含必要信息,减少数据库查询。
- 跨域支持:可在不同域名间传递,适合单点登录(SSO)场景。
缺点:
- 无法即时吊销:一旦签发,在过期前始终有效(除非服务器维护黑名单,违背无状态特性)。
- Payload 无加密:Base64Url 编码可解码,敏感信息不能放入。
- 长度问题:包含较多信息时,JWT 较长,可能增加请求体积。
| 特性 | JWT | Session |
|---|---|---|
| 存储位置 | 客户端(localStorage 等) | 服务器(内存 / 数据库) |
| 状态管理 | 无状态(服务器不存储) | 有状态(服务器需维护会话) |
| 扩展性 | 适合分布式系统 | 需共享 Session(如 Redis) |
| 安全性 | 签名防篡改,无加密 | 依赖 Cookie,需防 CSRF |
| 吊销机制 | 较复杂(需黑名单) | 直接删除服务器 Session |
使用场景建议
- 适合:API 认证、移动端应用、单点登录(SSO)、短期有效操作(如邮件验证链接)。
- 不适合:需要即时吊销令牌、存储敏感信息、长期有效的场景。
安全注意事项
-
避免在 Payload 中存放敏感数据(如密码)。
-
合理设置过期时间(
exp),减少令牌泄露风险。 -
使用 HTTPS 传输 JWT,防止中间人攻击。
-
选择合适的签名算法(如 RS256 非对称算法,避免使用 HS256 时泄露密钥)。
通过以上特性,JWT 成为现代 Web 应用中轻量级、高效的身份验证方案,但需根据实际场景权衡其优缺点。