[TIL 76일 차] Sprint Mission10
오늘의 성취
1. 개발 진행 상황
- 리팩터링 - 토큰 상태 관리
JwtRegistry인테페이스 구현 후InMemoryJwtRegistry구현체 구현JwtAuthenticationFilter에서JwtRegistry를 활용해 토큰의 상태를 검사하는 로직을 추가JwtRegistry를 활용해 동시 로그인 제한 기능을 리팩토링- 동일한 계정으로 로그인 시 기존 로그인 세션을 무효화
JwtRegistry를 활용해 권한이 변경된 사용자가 로그인 상태라면 강제로 로그아웃되도록 구현JwtRegistry를 활용해 사용자의 로그인 여부를 판단하도록 리팩토링.JwtLogoutHandler에서JwtRegistry를 활용해 로그아웃 시 토큰을 무효화@Scheduled를 활용해 주기적으로 만료된 토큰 정보를 레지스트리에서 삭제
프로젝트 요구 사항
//...
4. 심화 요구사항
4-01. 리팩토링 - 토큰 상태 관리
- 토큰 기반 인증 방식은 세션 기반 인증 방식과 달리 무상태(stateless)이기 때문에 사용자의 로그인 상태를 제어하기 어렵습니다.
- 따라서
SessionRegistry를 통해 세션의 상태를 관리했던 것처럼, JWT의 상태를 관리할 수 있는 컴포넌트를 추가해야합니다. - 토큰의 상태를 관리하는
JwtRegistry를 구현하세요.JwtRegistryregisterJwtInformation- 로그인 성공 시
JwtInformation을 등록합니다. - 최대 동시 로그인 수(
1)를 제어합니다.
- 로그인 성공 시
invalidateJwtInformationByUserId: UserId로 해당 유저의 모든JwtInformation정보를 삭제합니다.hasActiveJwtInformationBy*:JwtInformation이 Registry에 존재하는지 확인합니다.ByUserId: 사용자의 로그인 상태를 판단할 때 활용합니다.ByAccessToken: 필터에서 유효한 토큰인지 확인할 때 활용합니다.ByRefreshToken: 토큰 재발급 시 유효한 토큰인지 확인할 때 활용합니다.
rotateJwtInformation: 토큰 재발급 시 토큰 로테이션을 수행합니다.clearExpiredJwtInformation: 만료된JwtInformation을 삭제합니다.
InMemoryJwtRegistry- 메모리에
JwtInformation을 저장하는JwtRegistry구현체입니다. -
동시성 처리를 위해 다음과 같이 구성하세요. 동시성에 대해서는 다음 미션에서 학습합니다.
public class InMemoryJwtRegistry implements JwtRegistry { // <userId, Queue<JwtInformation>> private final Map<UUID, Queue<JwtInformation>> origin = new ConcurrentHashMap<>(); private final int maxActiveJwtCount; ... }
- 메모리에

JwtAuthenticationFilter에서JwtRegistry를 활용해 토큰의 상태를 검사하는 로직을 추가하세요.JwtRegistry를 활용해 동시 로그인 제한 기능을 리팩토링하세요.- 동일한 계정으로 로그인 시 기존 로그인 세션을 무효화합니다.
JwtRegistry를 활용해 권한이 변경된 사용자가 로그인 상태라면 강제로 로그아웃되도록 하세요.JwtRegistry를 활용해 사용자의 로그인 여부를 판단하도록 리팩토링하세요.-
JwtLogoutHandler에서JwtRegistry를 활용해 로그아웃 시 토큰을 무효화하세요.@Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { ... Arrays.stream(request.getCookies()) .filter(cookie -> cookie.getName().equals(JwtTokenProvider.REFRESH_TOKEN_COOKIE_NAME)) .findFirst() .ifPresent(cookie -> {...}); ... }- 로그아웃 API는 인증이 필요없기 때문에
Authentication정보가 없을 수 있습니다. - 따라서 요청 쿠키의 리프레시 토큰을 활용해 토큰을 무효화합니다.
- 로그아웃 API는 인증이 필요없기 때문에
- 주기적으로 만료된 토큰 정보를 레지스트리에서 삭제하세요.
-
@EnableScheduling를 추가하세요.@Configuration @EnableJpaAuditing @EnableScheduling public class AppConfig { } -
@Scheduled를 활용해서 5분마다 만료된 토큰을 삭제하세요.@Scheduled(fixedDelay = 1000 * 60 * 5) @Override public void clearExpiredJwtInformation() {...}
-
GitHub Repository 주소
https://github.com/JungH200000/10-sprint-mission/tree/sprint10
Leave a comment