스프링 시큐리티로 로그인, 로그아웃을 구현하다 보면 애매르송한 부분이 한둘이 아니다. login controller를 만들지 않아도 'http://localhost:8080/login"으로 로그인이 된다. 여기서 애매르송한게 '스프링 부트 3 백엔드 개발자 되기' 책을 보면 login controller는 만들지 않았는데 logout controller는 만든다. 그럼 이제 로그아웃 구현 여러가지 시도해보자
1. RESTful API 방식 로그아웃
// 로그아웃
@GetMapping("/api/logout")
public ResponseEntity<String> logout(HttpServletRequest request, HttpServletResponse response) {
/*
SecurityContextLogoutHandler:Spring Security에서 제공하는 로그아웃 핸들러
핸들러는 사용자의 세션을 종료하고 인증 정보를 삭제함.
logout() 메서드는 request, response,
그리고 현재 사용자 인증 정보를 담고 있는 Authentication 객체를 인자로 받음
이 인증 정보로 로그아웃, 세션 무효화, 쿠키게 저장된 인증 정보 제거함.
*/
new SecurityContextLogoutHandler().logout(request, response,
SecurityContextHolder.getContext().getAuthentication());
return ResponseEntity.ok("message : logout Successful");
}
설명은 위에 달았고 책에 나오는 코드와는 다르지만 response에 해당 코드가 실제로 동작 했는지 구현했다. 이 방식은 로그아웃 구현 방식 중에 RESTful API 방식 로그아웃으로 로그아웃 후 JSON 응답을 찍어보기 위한 방식이다. 그러면 로그아웃 하면 어느 페이지로 가게 되는걸까?
.logout(logout -> logout
.logoutSuccessUrl("/login")
.invalidateHttpSession(true))
WebSecurityConfig 파일에 해당 코드를 작성했을 텐데 로그아웃을 하면 spring security가 사용자를 '/login' url로 친히 모셔다 주는 서비스까지 한다.
postman으로 확인한 결과 controller가 잘 실행 되어서 body에 메세지가 찍힌 것을 볼 수 있다. 만약 postman으로 로그인 하는 방법을 모른다면 직접 쓴 아래 글을 보면 된다.
https://strolrol.tistory.com/88
2. WebSecurityConfig 로그아웃
로그인 컨트롤러를 안만든 것 처럼 WebSecurityConfig에서도 로그아웃을 설정할 수 있다. 즉 이 방식은 RESTful API를 사용하지 않는 방식이다.
/*
이전 버전 : extends WebSecurityConfigureAdapter 상속받음, anthMatchers("/") 사용
이후 버전 : 상속 대신 @Bean등록, requestMatchers("/") 사용
스프링 3.1.x 이후 (스프링 6.1.x) : 무조건 람다, 열겨식으로 쓰지 말것. -> .and() 쓰지 말것
*/
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChin(HttpSecurity http) throws Exception {
http.logout(logout -> logout
.logoutUrl("/logout") // 로그아웃 URL
.logoutSuccessUrl("/") // 로그아웃 성공 후 리다이렉트
.invalidateHttpSession(true) // 세션 무효화
.deleteCookies("JSESSIONID") // 쿠키 삭제
);
}
- logoutUrl : 로그아웃 url이다. RESTFull api에서 mapping한 '/api/logout' 메소드 대신에 위 한 문장으로 로그아웃이 된다.
- logoutSeccessUrl : 로그아웃 후 이동 할 페이지 url을 입력한다.
- invalidateHttpSession(true) : 시큐리티에서 제공한 세션을 만료시킨다.
- deleteCookies("JESSIONID") : 쿠키를 삭제한다.
postman으로 실행했을 때 로그아웃이 잘 된다.
1번과 같이 명시적으로 쓸 수 있지만, 반환 값을 굳이 주지 않는 경우가 아니면 아래와 같이 작성한다. spring security를 사용하는 의미가 많이 퇴색되고, RESTFull API 코드가 좀 더 복잡하다.
현재 10/25일 OAuth가 정리가 안되서 나중에 다시 쓸 예정이다.
[결론] : 끝이 없는 springSecurity