94 lines
2.9 KiB
Java
94 lines
2.9 KiB
Java
|
|
package com.ga.common.auth;
|
||
|
|
|
||
|
|
import com.ga.common.exception.BizException;
|
||
|
|
import com.ga.common.exception.ErrorCode;
|
||
|
|
import io.jsonwebtoken.Claims;
|
||
|
|
import io.jsonwebtoken.ExpiredJwtException;
|
||
|
|
import io.jsonwebtoken.Jwts;
|
||
|
|
import io.jsonwebtoken.JwtException;
|
||
|
|
import io.jsonwebtoken.security.Keys;
|
||
|
|
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.List;
|
||
|
|
import java.util.Map;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* JWT 발급/검증.
|
||
|
|
*/
|
||
|
|
@Slf4j
|
||
|
|
@Component
|
||
|
|
public class JwtTokenProvider {
|
||
|
|
|
||
|
|
private final SecretKey key;
|
||
|
|
private final long accessExpire;
|
||
|
|
private final long refreshExpire;
|
||
|
|
|
||
|
|
public JwtTokenProvider(
|
||
|
|
@Value("${ga.jwt.secret}") String secret,
|
||
|
|
@Value("${ga.jwt.access-token-expire:7200000}") long accessExpire,
|
||
|
|
@Value("${ga.jwt.refresh-token-expire:604800000}") long refreshExpire
|
||
|
|
) {
|
||
|
|
byte[] raw = secret.getBytes(StandardCharsets.UTF_8);
|
||
|
|
// 256비트 미만이면 안전하게 패딩
|
||
|
|
if (raw.length < 32) {
|
||
|
|
byte[] padded = new byte[32];
|
||
|
|
System.arraycopy(raw, 0, padded, 0, raw.length);
|
||
|
|
raw = padded;
|
||
|
|
}
|
||
|
|
this.key = Keys.hmacShaKeyFor(raw);
|
||
|
|
this.accessExpire = accessExpire;
|
||
|
|
this.refreshExpire = refreshExpire;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String createAccessToken(Long userId, String loginId, List<String> roles) {
|
||
|
|
return create(userId, loginId, roles, accessExpire, "ACCESS");
|
||
|
|
}
|
||
|
|
|
||
|
|
public String createRefreshToken(Long userId, String loginId) {
|
||
|
|
return create(userId, loginId, List.of(), refreshExpire, "REFRESH");
|
||
|
|
}
|
||
|
|
|
||
|
|
private String create(Long userId, String loginId, List<String> roles, long expireMs, String type) {
|
||
|
|
Date now = new Date();
|
||
|
|
return Jwts.builder()
|
||
|
|
.subject(loginId)
|
||
|
|
.claims(Map.of(
|
||
|
|
"uid", userId,
|
||
|
|
"roles", roles,
|
||
|
|
"type", type
|
||
|
|
))
|
||
|
|
.issuedAt(now)
|
||
|
|
.expiration(new Date(now.getTime() + expireMs))
|
||
|
|
.signWith(key)
|
||
|
|
.compact();
|
||
|
|
}
|
||
|
|
|
||
|
|
public Claims parse(String token) {
|
||
|
|
try {
|
||
|
|
return Jwts.parser().verifyWith(key).build()
|
||
|
|
.parseSignedClaims(token).getPayload();
|
||
|
|
} catch (ExpiredJwtException e) {
|
||
|
|
throw new BizException(ErrorCode.TOKEN_EXPIRED);
|
||
|
|
} catch (JwtException | IllegalArgumentException e) {
|
||
|
|
throw new BizException(ErrorCode.TOKEN_INVALID);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public boolean isValid(String token) {
|
||
|
|
try {
|
||
|
|
parse(token);
|
||
|
|
return true;
|
||
|
|
} catch (Exception e) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public long getAccessExpire() { return accessExpire; }
|
||
|
|
public long getRefreshExpire() { return refreshExpire; }
|
||
|
|
}
|