[Redis] security redis session logout 구현

김정연·2024년 11월 12일
0

oauth2 & redis

목록 보기
2/3
post-thumbnail

로그아웃 시점에 레디스에서 세션이 삭제되는게 목표여서 시큐리티에서 로그아웃을 구현해봤다.

로그인 시점에 쿠키와 레디스에 refreshToken이 들어가고 로컬스토리지에 acessToken을 넣기 위해 리턴 값으로 넣었다. 그리고 로그아웃 시점에는 세션을 삭제하고 쿠키를 삭제하는게 목표이다.

두 이미지는 포스트 맨으로 로그인 요청을 보냈을 때 확인할 수 있는 값이다. 실제로 레디스에서도 세션 정보를 확인했다.

스프링 시큐리티 로그아웃

스프링 시큐리티는 기본적으로 로그아웃을 지원하고 있다. 서버에 로그아웃 요청을 보내면

  • 세션 무효화
  • 쿠키 삭제
  • SecurityContext 초기화
  • 리다이렉트

총 네가지를 지원한다. 여기서 나는 쿠키삭제와 리다이렉트만 사용할 예정이다.

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().permitAll())
                .logout(logout -> logout
                        .logoutUrl("/logout")
                        .addLogoutHandler((request, response, authentication) -> {
                            sessionInfo.logout();
                        })
                        .logoutSuccessHandler(customerLogoutHandler)
                        .deleteCookies("JSESSIONID", "refreshToken")
                );
        return http.build();
    }

csrf 비활성화

우리는 JWT 토큰을 인증기반으로 사용하기 때문에 비활성화 했다.

addLogoutHandler

addLogoutHandler 메서드는 로그아웃 요청이 들어올 때 어떻게 동작할지에 대해 정의하는 것이다.
나는 redis에서 세션값만 지우면 되기 때문에 따로 설정해둔 logout 메서드를 동작하게 했다.
그리고 쿠키에 있는 리프레쉬 토큰도 삭제하게 했다.

로그아웃시 레디스에서 세션을 지우는게 아닌 데이터만 지우는 이유!!

초반에 말했듯이 세션 자체를 레디스에서 지우기 위해 레디스 템플릿으로 직접 접근하려고 했는데 그렇게 하지 않는 이유가 있는 것 같아 알아봤다.

  • 세션 자체를 삭제하면 세션 키가 레디스에서 사라져 다른 시스템이나 컴포넌트에 영향을 미칠 수 있다.
  • 세션 키를 삭제하지 않고 데이터만 지움으로써 사용자가 같은 세션ID로 접속하더라도 세션을 재사용 할 수 있다.
  • 일부 시스템에서는 비인증 관련 데이터를 저장하는데 사용될 수 있다.
  • 세션 재사용이 가능해 매번 세션을 새로 생성하거나 삭제하는 일이 없어 성능 최적화가 가능하다.

즉 로그아웃 시점에 굳이 세션을 삭제하는 것이 아닌 사용자 관련 데이터만 지우는 것이 이점이 더 많았다.

이렇게 간단하게 구현이 가능했다. 그리고 로그아웃 성공 핸들러를 통해 사이드 프로젝트의 컨벤션에 맞춰 리턴값도 따로 맞춰줬다.

로그아웃 커스텀 핸들러

상단에 보면 현재 프로젝트의 공통코트는 code, message, results 이다. 시큐리티 내에서 작성해보니 가독성이 많이 떨어지고 나중에 추가 기능을 만들 가능성이 있어 로그아웃 성공 핸들러를 따로 작성해줬다.

@Component
public class CustomerLogoutHandler implements LogoutSuccessHandler {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        response.setStatus(HttpServletResponse.SC_OK);
        ObjectMapper objectMapper = new ObjectMapper();

        Map<String, Object> jsonResponse = new HashMap<>();
        jsonResponse.put("code", 20000);
        jsonResponse.put("message", "요청 성공");
        jsonResponse.put("results", ~~~~~~

    }
}

이렇게 필요한 내용만 뽑아서 커스텀해서 사용이 가능한게 너무 편리했다.
레디스도 설정 다했으니 이제 이메일 인증 구현을 시작해야겠다.

profile
백엔드 개발자

0개의 댓글