Java中的JWT令牌:创建、验证与使用
JSON Web Token (JWT) 是一种紧凑且自包含的方式,以JSON对象的形式在各方之间传输信息。在Java中,JWT广泛用于REST API和微服务架构中的认证、授权和数据交换。本文将介绍Java中最流行的两个JWT库——Stormpath的JJWT (Java JWT) 和Auth0的java-jwt,并探讨如何与Spring Security集成。
什么是JWT以及为什么需要它?
JWT由三个部分组成,用点号分隔:
- Header — 头部,包含令牌类型和签名算法(例如HS256或RS256)。
- Payload — 有效载荷,包含声明(claims),如用户ID、角色、过期时间。
- Signature — 签名,基于header、payload和密钥生成。
在Java中,JWT最常用于:
- 无状态用户认证(无需在服务器保存会话)。
- 在微服务之间传递访问权限。
- 用于密码重置或邮箱确认的一次性令牌。
JJWT库 (io.jsonwebtoken)
JJWT 是Java中最流行的JWT库。它易于使用,支持所有标准算法(HS256、RS256、ES256),并且持续更新。
通过Maven引入JJWT
<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>创建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 token = Jwts.builder() .subject("user123") .claim("role", "admin") .issuedAt(new Date()) .expiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时 .signWith(key) .compact();
System.out.println("生成的JWT: " + token); }}验证和解析JWT
import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jws;import io.jsonwebtoken.JwtException;import io.jsonwebtoken.Jwts;
public class JwtParserExample { public static void main(String[] args) { String jwtToken = "eyJhbGciOiJIUzI1NiJ9..."; // 你的令牌 SecretKey key = ...; // 与创建时相同的密钥
try { Jws<Claims> claimsJws = Jwts.parser() .verifyWith(key) .build() .parseSignedClaims(jwtToken);
Claims claims = claimsJws.getPayload(); System.out.println("Subject: " + claims.getSubject()); System.out.println("Role: " + claims.get("role")); System.out.println("Expiration: " + claims.getExpiration()); } catch (JwtException e) { System.out.println("令牌无效: " + e.getMessage()); }