JwtUtil.java

package org.darkroomlibrary.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

/**
 * Creates and validates application JWT access tokens.
 */
@Slf4j
@Component
public class JwtUtil {

    private final String secret;
    private final long expiration;

    public JwtUtil(
            @Value("${jwt.secret}") String secret,
            @Value("${jwt.expiration}") long expiration) {
        this.secret = secret;
        this.expiration = expiration;
    }

    private SecretKey getKey() {
        return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 生成 token
     *
     * @param id   用户ID
     * @param role 用户角色
     * @param authVersion 认证状态版本
     * @return String
     */
    public String toToken(Integer id, Integer role, Integer authVersion) {
        return Jwts.builder()
                .header()
                .type("JWT")
                .and()
                .claim("id", id)
                .claim("role", role)
                .claim("authVersion", authVersion)
                .subject("用户认证")
                .expiration(new Date(System.currentTimeMillis() + expiration))
                .id(UUID.randomUUID().toString())
                .signWith(getKey())
                .compact();
    }

    /**
     * 解密TOKEN,区分不同异常类型
     *
     * @param token token信息
     * @return JWT Claims,解析失败返回 null
     */
    public Claims fromToken(String token) {
        if (token == null || token.isEmpty()) {
            return null;
        }
        JwtParser jwtParser = Jwts.parser().verifyWith(getKey()).build();
        try {
            return jwtParser.parseSignedClaims(token).getPayload();
        } catch (ExpiredJwtException e) {
            log.debug("Token已过期: {}", e.getMessage());
            return null;
        } catch (SignatureException e) {
            log.debug("Token签名无效: {}", e.getMessage());
            return null;
        } catch (Exception e) {
            log.debug("Token解析失败: {}", e.getMessage());
            return null;
        }
    }
}