본문 바로가기

개발

[Spring Cloud Gateway] 로그아웃 확인

[로그아웃 로직]

  1. accessToken과 email을 받음
  2. email 값으로 Redis내의 Refresh:{email} 삭제
  3. accessToken은 따로 저장되어있는 곳이 없기때문에 로그아웃 처리 시 redis에 logout:{accessToken}으로 저장한다.
  4. 인가 필터에서 accessToken이 redis의 logout:{accessToken} 으로 저장되어있는지 확인한다.
  5. true → Exception 처리

 

 

1. module-common → [AuthController]

/**
     * 로그아웃
     * 1. Redis내의 refresh_token 삭제
     * 2. Redis에 현재 access_token을 logout 상태로 등록
     * - 2.1. 해당 access_token의 남은 유효시간을 Redis의 TTL로 등록
     * 3. JwtTokenFilter 파일의 doFIlterInternal 메소드에서 redis에 logout 상태인지 검증하는 로직 추가
     * */
    @DeleteMapping("/logout")
    public ResponseEntity<?> logout(@RequestHeader("ACCESS_TOKEN") String accessToken, @RequestBody LogoutRequest request) {
        authService.logout(accessToken, request);
        return ResponseEntity.status(HttpStatus.OK).body("User logout!");
    }

 

 

2. module-common → [AuthServiceImpl]

public void logout(String accessToken, LogoutRequest request) {
        String email = request.getEmail();
        // Redis 내의 기존 refreshToken 삭제
        if (!refreshTokenRepository.existsById(email)){
            // 리프레시 토큰 없다고 예외처리 날려야됨
        }
        refreshTokenRepository.deleteById(email);
        // access_token의 남은 유효시간 가져오기 (Seconds 단위)
        Date expirationFromToken = jwtTokenProvider.getExpirationFromToken(accessToken);
        Date today = new Date();
        Integer sec = (int) ((expirationFromToken.getTime() - today.getTime()) / 1000);

        // access_token을 Redis의 key 값으로 등록
        logoutRepository.save(
                Logout.builder()
                        .id(accessToken)
                        .data("logout")
                        .expiration(sec)
                        .build()
        );
    }

 

 

3. apigateway → [JwtUtil]에 로그아웃 확인 로직 추가

/**
     * 로그아웃 로직
     * */
    public boolean isTokenLogout(String token) {
        // Redis에 해당 토큰이 존재하는지 확인
        return Boolean.TRUE.equals(redisTemplate.hasKey(getRedisKeyForToken(token)));
    }

    private String getRedisKeyForToken(String token) {
        return "logout:" + token;
    }

 

 

4. apigateway → [AuthenticationFilter]에 로그아웃 확인 로직 추가

try {
    jwtUtil.validateToken(token);

    // 로그아웃 체크
    if (jwtUtil.isTokenLogout(token)) {
        throw new UnauthorizedAccessException();
    }
} catch (Exception e) {
    throw new UnauthorizedAccessException();
}

 

RemoveRequestHeader=Cookie

현재 이 필터를 apigateway의 .yml파일에서 사용하고 있는데 logout을 하는 과정에서

@RequestHeader("ACCESS_TOKEN") String accessToken

이 코드에 문제가 생기진 않을까 생각했음

결론적으로 문제가 생기진 않았고, 만약 RemoveRequestHeader=Authorization을 쓸 경우 문제가 생김!!!!!!!!!!

jwt를 사용하면 쿠키를 사용하지 않는걸로 아는데 사람들의 코드에도 다 RemoveRequestHeader=Cookie 필터가 있던데 왜 굳이 사용하는걸까..?