https://velog.io/@c65621/JWT-%ED%8F%90%EA%B8%B0
JWT는 불변(immutable)한 특성을 가진 토큰
없다!
사용자의 정보가 업데이트된 후, 새로운 JWT를 발급한다. 이후 클라이언트 측에서 새로운 토큰을 받아서 이전 토큰을 교체하도록 한다.
리프레시 토큰 : JWT와 함께 사용하는 추가적인 보안 메커니즘
액세스 토큰: 짧은 유효 기간을 가진 토큰으로, 인증이 필요한 요청에 사용됩니다.
리프레시 토큰: 상대적으로 긴 유효 기간을 가진 토큰으로, 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받기 위해 사용됩니다.
리프레시 토큰의 사용 방식은 다음과 같습니다:
로그인 시: 클라이언트는 액세스 토큰과 리프레시 토큰을 모두 받는다.
액세스 토큰 만료 시: 클라이언트는 리프레시 토큰을 사용하여 새로운 액세스 토큰을 요청한다.
서버에서 리프레시 토큰 검증 및 새로운 액세스 토큰 발급: 서버는 리프레시 토큰을 검증한 후, 새로운 액세스 토큰을 발급한다.
서버 측에서 토큰을 블랙리스트에 추가, 더 이상 유효하지 않도록 한다.
1) BlacklistService
@Component
public class JwtBlacklistService {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String BLACKLIST_KEY = "jwt_blacklist";
public void addToBlacklist(String token, long expiration) {
redisTemplate.opsForHash().put(BLACKLIST_KEY, token, expiration);
}
public boolean isTokenBlacklisted(String token) {
return redisTemplate.opsForHash().hasKey(BLACKLIST_KEY, token);
}
public void removeExpiredTokens() {
// Implement token expiration cleanup logic here if needed
}
}
2)
public void invalidateToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody();
long expiration = claims.getExpiration().getTime();
jwtBlacklistService.addToBlacklist(token, expiration);
}
// 토큰 블랙리스트 체크
public boolean isTokenBlacklisted(String token) {
return blacklistedTokens.contains(token);
}
String token = requestDto.token(); // 클라이언트에서 제공된 토큰을 가져오는 방식으로 예시
if (token != null) {
jwtUtil.blacklistToken(token);
}
public boolean validateToken(String token) {
// 토큰이 블랙리스트에 있으면 유효하지 않음
if (jwtUtil.isTokenBlacklisted(token)) {
return false;
}
// 여기에 JWT의 유효성 검사를 추가
}
@AuthenticationPrincipal
별도의 토큰 검증을 수행할 필요 없다.
+) 직접적으로 토큰 검증을 수행하려면 JwtUtil 같은 클래스에서 토큰을 직접 검증해야 한다.
+) 어노테이션을 커스텀할 수 있다. https://m42-orion.tistory.com/163