package com.qf.backend.util; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.function.Function; import javax.crypto.SecretKey; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; /** * JWT工具类,用于生成和验证token(JJWT 0.12.x 版本) * 支持 Java 17+ 和 Jakarta EE(Spring Boot 3.x) */ @Component public class JwtUtils { @Value("${jwt.secret:default_secret_key_for_development}") private String secret; @Value("${jwt.expiration:3600000}") private long expiration; @Value("${jwt.token-prefix:Bearer}") private String tokenPrefix; /** * 获取签名密钥 */ private SecretKey getSignInKey() { byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8); return Keys.hmacShaKeyFor(keyBytes); } /** * 从token中获取用户名 */ public String getUsernameFromToken(String token) { return getClaimFromToken(token, Claims::getSubject); } /** * 从token中获取过期时间 */ public Date getExpirationDateFromToken(String token) { return getClaimFromToken(token, Claims::getExpiration); } /** * 从token中获取指定的claim */ public T getClaimFromToken(String token, Function claimsResolver) { final Claims claims = getAllClaimsFromToken(token); return claimsResolver.apply(claims); } /** * 获取token中的所有claims */ private Claims getAllClaimsFromToken(String token) { return Jwts.parser() .verifyWith(getSignInKey()) .build() .parseSignedClaims(token) .getPayload(); } /** * 检查token是否过期 */ private Boolean isTokenExpired(String token) { final Date expiration = getExpirationDateFromToken(token); return expiration.before(new Date()); } /** * 生成token */ public String generateToken(UserDetails userDetails) { Map claims = new HashMap<>(); claims.put("authorities", userDetails.getAuthorities()); return doGenerateToken(claims, userDetails.getUsername()); } /** * 生成token的核心方法 */ private String doGenerateToken(Map claims, String subject) { return Jwts.builder() .claims(claims) // 使用新的 claims() 方法 .subject(subject) // 使用新的 subject() 方法 .issuedAt(new Date(System.currentTimeMillis())) .expiration(new Date(System.currentTimeMillis() + expiration)) // 使用新的 expiration() 方法 .signWith(getSignInKey(), Jwts.SIG.HS256) // 使用新的签名方式 .compact(); } /** * 验证token */ public Boolean validateToken(String token, UserDetails userDetails) { final String username = getUsernameFromToken(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } /** * 获取token前缀 */ public String getTokenPrefix() { return tokenPrefix; } }