🐰 로그아웃을 하게 된다면 블랙리스트에 엑세스 토큰을 담고 만료가 될 때까지 사용을 하지 못하게 구현해 보았다.
HTTP 요청에서 토큰을 추출하고, token 변수에 저장한다.
해당 토큰이 유효한지 검증한다.
유효하지 않는다면 "유효하지 않은 토큰입니다" 메시지와 예외를 발생시킨다.
유효하다면 토큰을 블랙리스트에 추가한다.
"로그아웃 되었습니다." 메시지와 200 상태코드를 반환한다.
@RequestMapping("/api/logout")
public ResponseEntity<StatusResponseDto> logout(HttpServletRequest request, HttpServletResponse response)throws IOException {
String token = jwtUtil.resolveToken(request);
log.info("controller token: " + token);
// Access Token 검증
if (!jwtUtil.validateToken(token)) {
throw new IllegalArgumentException("유효하지 않은 토큰입니다.");
}
userService.logout(token);
return ResponseEntity.ok().body(new StatusResponseDto("로그아웃 되었습니다.", HttpStatus.OK.value()));
}
blackList 객체를 생성하고, token을 인자로 받는다.
블랙리스트에 해당 토큰을 추가한다.
public void logout(String token) {
// 토큰을 블랙리스트에 추가
BlackList blackList = new BlackList(token);
blackListRepository.save(blackList);
}
HTTP 요청의 헤더에서 Bearer로 시작하는 토큰을 추출하는 메서드
HttpServletRequest 객체를 인자로 받고 HTTP 요청의 헤더에서 AUTHORIZATION_HEADER 값을 가져와 bearerToken 변수에 저장한다.
bearerToken이 null이 아니고 Bearer로 시작하는 경우, bearerToken.substring(9)을 반환한다.
그렇지 않은 경우 null을 반환한다.
public String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
log.info("bearerToken : " + bearerToken);
if (StringUtils.hasText(bearerToken)&& bearerToken.startsWith("Bearer")) {
return bearerToken.substring(9);
}
return null;
}
토큰이 블랙리스트에 있는지 확인하는 메서드
블랙리스트에 해당 토큰이 있다면 blackList 변수에 저장하고 true를 반환한다.
그렇지 않은 경우 false를 반환
public boolean isBlacklist(String token) {
BlackList blackList = blackListRepository.findByToken(token).orElse(null);
return blackList != null;
}
블랙리스트와 관련되지 않은 부분은 생략한다.
HTTP 요청에서 토큰을 추출하여 블랙리스트에 있는지 확인하고, 만약 블랙리스트에 있다면 "이미 로그아웃된 토큰입니다."라는 메시지와 함께 401 상태코드를 반환한다.
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = jwtUtil.resolveToken(request);
// 중략
// 블랙리스트에 존재하는 토큰일 경우 조건문에 true 입력, 로그아웃된 토큰 메세지와 인증불가 코드 반환
if (jwtUtil.isBlacklist(token)) {
StatusResponseDto responseDto = new StatusResponseDto("이미 로그아웃된 토큰입니다.", HttpStatus.UNAUTHORIZED.value());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json; charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(responseDto));
return;
}
// 중략
}
🐰 토큰 만료시간을 1시간으로 설정해서 스케줄러는 따로 구현하지 않았지만 어떻게 사용하는지 알아보자
@Component
@Slf4j
public class Scheduler {
@Value("${spring.profiles.active}")
private String env;
@Scheduled(cron = "0 */5 * * * *") // 5분마다
public void test1() throws Exception {
if(!env.equals("prod")) {
log.info("매일 5분마다 - " + env);
}
}
@Scheduled(cron = "0 0 0 * * *") // 매일 00시 정각
public void test2() throws Exception {
log.info("매일 00시");
}
@Scheduled(cron = "0 * * * * *") // 1분마다
public void test3() throws Exception {
log.info("health check - " + env);
}
}
이런 유용한 정보를 나눠주셔서 감사합니다.