2025-05-20
UsernamePasswordAuthenticationToken
)@Slf4j
@Component
public class JwtTokenProvider {
@Autowired
private UserRepository userRepository;
@Autowired
private SignatureRepository signatureRepository;
// Key ์ ์ฅ - JWT ์๋ช
์ ์ฌ์ฉ
private Key key;
// SignatureScheduling์์ ์ฃผ์
์ ์ฌ์ฉ๋จ
public void setKey(Key key){
this.key = key;
}
// ์๋ฒ ์์ ์ ์๋ช
ํค ์ด๊ธฐํ
@PostConstruct
public void init(){
List<Signature> list = signatureRepository.findAll();
if(list.isEmpty()){
// ์ต์ด ์คํ: ์ ํค ์์ฑ ๋ฐ ์ ์ฅ
byte[] keyBytes = KeyGenerator.getKeygen();
this.key = Keys.hmacShaKeyFor(keyBytes);
Signature signature = Signature.builder()
.keyBytes(keyBytes)
.createAt(LocalDate.now())
.build();
signatureRepository.save(signature);
System.out.println("JwtTokenProvider init() ์ ๊ท Key ์์ฑ: " + key);
} else {
// ๊ธฐ์กด ์๋ช
ํค ๋ก๋
Signature signature = list.get(0);
this.key = Keys.hmacShaKeyFor(signature.getKeyBytes());
System.out.println("JwtTokenProvider init() ๊ธฐ์กด Key ์ฌ์ฉ: " + key);
}
}
// Access + Refresh Token ์์ฑ ๋ฉ์๋
public TokenInfo generateToken(Authentication authentication) {
String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
long now = System.currentTimeMillis();
// AccessToken ์์ฑ
Date accessTokenExpiresIn = new Date(now + JwtProperties.ACCESS_TOKEN_EXPIRATION_TIME);
String accessToken = Jwts.builder()
.setSubject(authentication.getName())
.claim("username", authentication.getName())
.claim("auth", authorities)
.setExpiration(accessTokenExpiresIn)
.signWith(key, SignatureAlgorithm.HS256)
.compact();
// RefreshToken ์์ฑ
String refreshToken = Jwts.builder()
.setExpiration(new Date(now + JwtProperties.REFRESH_TOKEN_EXPIRATION_TIME))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
System.out.println("AccessToken: " + accessToken);
System.out.println("RefreshToken: " + refreshToken);
return TokenInfo.builder()
.grantType("Bearer")
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
}
// JWT๋ก๋ถํฐ ์ธ์ฆ ๊ฐ์ฒด ์์ฑ
public Authentication getAuthentication(String accessToken) {
Claims claims = parseClaims(accessToken);
if (claims.get("auth") == null) {
throw new RuntimeException("๊ถํ ์ ๋ณด๊ฐ ์๋ ํ ํฐ์
๋๋ค.");
}
// ๊ถํ ์ ๋ณด ํ์ฑ
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get("auth").toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
// ์ฌ์ฉ์ ์ ๋ณด ๋ก๋ฉ
String username = claims.getSubject();
Optional<User> userOptional = userRepository.findById(username);
PrincipalDetails principalDetails = new PrincipalDetails();
if(userOptional.isPresent()) {
UserDto userDto = UserDto.toDto(userOptional.get());
principalDetails.setUserDto(userDto);
}
return new UsernamePasswordAuthenticationToken(principalDetails, "", authorities);
}
// JWT์ Claims ํ์ฑ (๋ง๋ฃ๋์ด๋ ํ์ฑ ๊ฐ๋ฅ)
private Claims parseClaims(String accessToken) {
try {
return Jwts.parserBuilder().setSigningKey(key).build()
.parseClaimsJws(accessToken).getBody();
} catch (ExpiredJwtException e) {
return e.getClaims(); // ๋ง๋ฃ๋๋๋ผ๋ ๋ด๋ถ ์ ๋ณด ์ถ์ถ
}
}
// JWT ์ ํจ์ฑ ๊ฒ์ฆ
public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
log.info("Invalid JWT Token", e);
} catch (UnsupportedJwtException e) {
log.info("Unsupported JWT Token", e);
} catch (IllegalArgumentException e) {
log.info("JWT claims string is empty.", e);
}
return false;
}
}
๋ฉ์๋ | ์ญํ |
---|---|
generateToken() | ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก JWT ์์ฑ (AT/RT) |
getAuthentication() | JWT๋ก๋ถํฐ ์ฌ์ฉ์ ์ ๋ณด์ ๊ถํ์ ๋ณต์ |
validateToken() | JWT ์๋ช ๊ณผ ๊ตฌ์กฐ ์ ํจ์ฑ ํ์ธ |
parseClaims() | ๋ง๋ฃ ์ฌ๋ถ์ ์๊ด์์ด Claim ํ์ฑ |
@PostConstruct init() | ์๋ฒ ์์ ์ ํค ๋ถ๋ฌ์ค๊ธฐ ๋๋ ์์ฑ |
setKey() | SignatureScheduling์์ key ๊ต์ฒด๋ฅผ ์ํ setter |
@PostConstruct
์ด๊ธฐํ ๋ก์ง๊ณผ SignatureScheduling
์ ์กฐํฉ์ผ๋ก, ์๋ฒ ์ฌ์์ ํ์๋ ์ผ๊ด๋ ํค ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ก๋ค./refresh
์๋ํฌ์ธํธ ๊ตฌํ์ผ๋ก ํ์ฅํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.์ด์ ์ด ๋ด์ฉ์ ๋ฒจ๋ก๊ทธ์ ๋ฐ๋ก ์ฌ๋ฆด ์ ์์ด! ๐
๋ค์ ํธ์์๋ ์๋ช ํค๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ๊ฐฑ์ ํ๋ SignatureScheduling ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฐ ์์ ์ด์ผ.
์ธ๋ค์ผ๋ ํ์ํ๋ฉด ๋ฐ๋ก ๋ง๋ค์ด์ค๊ฒ ๐
์ธ๋ค์ผ ๋ง๋ค์ด์ค๊น? ์๋๋ฉด 3ํธ ๋ฐ๋ก ์์ํ ๊น? ์ ํํด์ค!