JWT令牌在Java中:JSON Web Tokens完全操作指南
JSON Web Token (JWT) 是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,以JSON对象的形式在各方之间传输信息。在Java中,有多个成熟的库可用于处理JWT,这些库允许创建、签名、验证和解码令牌。在本文中,我们将详细介绍三个主要库:JJWT、Auth0 java-jwt 和 Nimbus JOSE + JWT,并分析其最佳实践。
什么是JWT,为什么在Java中需要它?
JWT由三部分组成,各部分之间用点分隔:
- Header — 包含令牌类型和签名算法的信息(例如HS256或RS256)。
- Payload — 包含声明(claims):标准声明(iss、sub、exp、iat)和自定义数据。
- Signature — 通过对header + payload进行哈希处理,使用密钥或RSA/ECDSA密钥对创建。
在Java中,JWT最常用于:
- REST API中的身份验证和授权(特别是与Spring Security结合使用)。
- 在微服务之间传输信息。
- 实现单点登录(SSO)。
JJWT库 (io.jsonwebtoken)
JJWT是Java中最流行且文档最完善的库之一。它支持所有现代签名和加密算法,并提供了便捷的fluent API。
安装
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.12.6</version></dependency><dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.12.6</version> <scope>runtime</scope></dependency><dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.12.6</version> <scope>runtime</scope></dependency>使用JJWT创建JWT
import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import io.jsonwebtoken.security.Keys;import javax.crypto.SecretKey;import java.util.Date;
public class JwtExample { public static void main(String[] args) { // 为HS256生成安全密钥 SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
String jwt = Jwts.builder() .subject("user123") .issuer("https://pythonlib.ru") .issuedAt(new Date()) .expiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时 .claim("role", "ADMIN") .signWith(key) .compact();
System.out.println("JWT: " + jwt); }}验证和解析JWT
import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jws;import io.jsonwebtoken.Jwts;
public class JwtParser { public static void main(String[] args) { String jwt = "eyJhbGciOiJIUzI1NiJ9..."; // 您的令牌 SecretKey key = ...; // 与签名时使用的相同密钥
try { Jws<Claims> claimsJws = Jwts.parser() .verifyWith(key) .build() .parseSignedClaims(jwt); Claims claims = claimsJws.getPayload(); String subject = claims.getSubject(); String role = claims.get("role", String.class); System.out.println("Subject: " + subject); System.out.println("Role: " + role); } catch (Exception e)