스프링 시큐리티 로그아웃 기능

WAS·6일 전
0

Spring Security

목록 보기
2/2

✅ 스프링 시큐리티 로그아웃 기능 이란?

  • 인증 된 사용자가 로그아웃 요청을 했을 때
    (서버세션 무효화, 인증정보와 쿠키 삭제, SecurityContext 도 비워주는) 보안 기능이다

  • 이 과정을 통해 사용자는 안전하게 로그아웃 되고, 이후에는 인증이 필요한 리소스에 접근 불가능

SecurityContext : 현재 인증된 사용자의 정보권한 을 담고 있는 컨테이너(저장소)


✅ 기본적인 코드 구조

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.logout()
            .logoutUrl("/logout") // 로그아웃 처리 URL
            .logoutSuccessUrl("/login") // 로그아웃 성공 후 이동할 URL
            .invalidateHttpSession(true) // 세션 무효화
            .deleteCookies("JSESSIONID", "remember-me") // 쿠키 삭제
            .addLogoutHandler(logoutHandler()) // 추가 로그아웃 핸들러(선택)
            .logoutSuccessHandler(logoutSuccessHandler()); // 커스텀 성공 핸들러(선택)
    }
}

logoutUrl("/logout") : 로그아웃 요청을 받을 URL 지정

logoutSuccessUrl("/login") : 로그아웃 후 이동할 URL 지정

invalidateHttpSession(true) : 세션 무효화

deleteCookies(...) : 쿠키 삭제

addLogoutHandler(...) : 커스텀 핸들러 추가(선택)

logoutSuccessHandler(...) : 로그아웃 성공 시 실행할 핸들러(선택)

여기서 커스텀 로그아웃 핸들러는 따로 작성하면 된다

.addLogoutHandler((request, response, authentication) -> {
    // 추가 로그아웃 작업
})
.logoutSuccessHandler((request, response, authentication) -> {
    response.sendRedirect("/login");
})

✅ Oauth 로그아웃과 일반 로그아웃 함께 구현

.logout(logout -> logout
			.logoutUrl("/logout") // 로그아웃을 수행할 엔드포인트 URL을 지정 (사용자가 /logout으로 접속하면 이 설정이 실행)
			.logoutSuccessHandler((request, response, authentication) -> { // 로그아웃이 성공적으로 처리된 후 실행되는 직접 구현한 로직
						    	
		// 현재 세션 종료 및 인증 해제
			HttpSession session = request.getSession(false);
				if (session != null) { // 현재 세션이 존재하면
					session.invalidate();  // 세션을 강제로 무효화
				}
                    
			SecurityContextHolder.clearContext(); // Spring Security의 SecurityContext (로그인 정보 저장소) 를 초기화
						        
			// 로그아웃 후 리다이렉트 주소에 사용하기 위해 서버의 주소를 동적으로 생성
			String currentHost = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();

			 	// 인증이 null인 경우 → 로그인 상태 아님 → 그냥 로그인 페이지로 보냄
				if (authentication == null) {
						response.sendRedirect(currentHost + "/login"); // /login 페이지로 리다이렉트
						return;
				}

				// OAuth 로그인인지 확인 (카카오/구글 같은 OAuth2 로그인 사용자일 경우 true)
				boolean isOauthUser = authentication.getPrincipal() instanceof org.springframework.security.oauth2.core.user.DefaultOAuth2User;

				if (isOauthUser) {
					// 🔒 카카오 로그아웃 URL로 리다이렉트
					String kakaoLogoutUrl = "https://kauth.kakao.com/oauth/logout" +
						                    "?client_id=" + KakaoConfig.CLIENT_ID +
						                    "&logout_redirect_uri=" + URLEncoder.encode(currentHost + "/login", "UTF-8");
						            response.sendRedirect(kakaoLogoutUrl);
				 } else {
						 response.sendRedirect(currentHost + "/login"); // 일반 로그인 사용자 → 일반 로그아웃 처리
					}

					})
						.invalidateHttpSession(true) // true -> 로그아웃 시 세션을 자동으로 무효화 (위에서 수동으로 했지만 이중으로 함)
						.deleteCookies("JSESSIONID") // 로그아웃할 때 클라이언트에 저장된 세션 쿠키(JSESSIONID) 도 삭제 (보안을 위해서)
						.permitAll()  // 누구나 접근 가능 
					);
profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글