import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
* JWT 工具類
*
* @author stonffe
* @date 2024/4/18
*/
@ConditionalOnProperty("novel.jwt.secret")
@Component
@Slf4j
public class JwtUtils {
/**
* 注入JWT加密金鑰
*/
@Value("${novel.jwt.secret}")
private String secret;
/**
* 定義系統標識頭常量
*/
private static final String HEADER_SYSTEM_KEY = "systemKeyHeader";
/**
* 根據使用者ID生成JWT
*
* @param uid 使用者ID
* @param systemKey 系統標識
* @return JWT
*/
public String generateToken(Long uid, String systemKey) {
long nowMillis = System.currentTimeMillis();
long expMillis = nowMillis + 60 * 60 * 1000;
return Jwts.builder()
.setHeaderParam(HEADER_SYSTEM_KEY, systemKey)
.setSubject(uid.toString())
// .setExpiration(new Date(expMillis))
.signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.compact();
}
/**
* 解析JWT返回使用者ID
*
* @param token JWT
* @param systemKey 系統標識
* @return 使用者ID
*/
public Long parseToken(String token, String systemKey) {
Jws<Claims> claimsJws;
try {
claimsJws = Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(token);
// OK, we can trust this JWT
// 判斷該 JWT 是否屬於指定系統
if (Objects.equals(claimsJws.getHeader().get(HEADER_SYSTEM_KEY), systemKey)) {
return Long.parseLong(claimsJws.getBody().getSubject());
}
} catch (JwtException e) {
log.warn("JWT解析失敗:{}", token);
// don't trust the JWT!
}
return null;
}
}