Files
myplayer-backend/src/main/java/xin/merlin/myplayerbackend/utils/JwtUtil.java
2025-11-17 18:02:58 +08:00

110 lines
3.2 KiB
Java

package xin.merlin.myplayerbackend.utils;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import xin.merlin.myplayerbackend.config.security.JwtProperties;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;
@Component
@RequiredArgsConstructor
public class JwtUtil {
private final JwtProperties jwtProperties;
private SecretKey key;
private JwtParser jwtParser;
@PostConstruct
public void init() {
try {
// 从配置文件密钥生成 SecretKey
this.key = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8));
this.jwtParser = Jwts.parser()
.verifyWith(key)
.build();
} catch (Exception e) {
throw new RuntimeException("JWT 密钥初始化失败,请检查配置文件 jwt.secret", e);
}
}
/**
* 生成 JWT Token
*/
public String generateToken(String account, Integer id) {
Date now = new Date();
Date expireDate = new Date(now.getTime() + jwtProperties.getExpire() * 1000L);
return Jwts.builder()
.subject(account)
.claim("id", id)
.claim("account", account)
.id(UUID.randomUUID().toString())
.issuedAt(now)
.expiration(expireDate)
.issuer(jwtProperties.getIssuer())
.signWith(key, Jwts.SIG.HS256) // JJWT 0.12.6推荐的写法
.compact();
}
/**
* 解析 Token 获取 Claims
*/
public Claims getClaims(String token) {
try {
Jws<Claims> jws = jwtParser.parseSignedClaims(token);
System.out.println(jws.getPayload());
return jws.getPayload();
} catch (ExpiredJwtException e) {
throw new TokenExpiredException("Token 已过期", e);
} catch (JwtException e) {
throw new InvalidTokenException("无效的 Token", e);
} catch (Exception e) {
throw new InvalidTokenException("解析 Token 失败", e);
}
}
/**
* 判断 Token 是否过期
*/
public boolean isTokenExpired(String token) {
Claims claims = getClaims(token);
return claims.getExpiration().before(new Date());
}
/**
* 获取账号
*/
public String getAccount(String token) {
Claims claims = getClaims(token);
return claims.getSubject();
}
/**
* 获取用户ID
*/
public Integer getId(String token) {
Claims claims = getClaims(token);
return claims.get("id", Integer.class);
}
// 自定义异常类
public static class TokenExpiredException extends RuntimeException {
public TokenExpiredException(String message, Throwable cause) {
super(message, cause);
}
}
public static class InvalidTokenException extends RuntimeException {
public InvalidTokenException(String message, Throwable cause) {
super(message, cause);
}
}
}