Spring

스프링부트 커뮤니티 만들기 #3 - 로그아웃, 회원탈퇴

chaewonni 2024. 2. 27. 02:20

저번에 만들었던 회원가입, 로그인 로직에 이어 이번에는 로그아웃, 회원탈퇴 기능을 구현해보았다.


SecurityConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    //비밀번호 해시화
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .httpBasic(httpBasicConfigurer -> httpBasicConfigurer.disable())  // HTTP Basic 인증 비활성화
                .csrf(CsrfConfigurer::disable)  // CSRF 보호 기능 비활성화
                .cors(corsConfigurer -> corsConfigurer.configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues()))
                .sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
                .authorizeHttpRequests(authorizeRequestsCustomizer -> authorizeRequestsCustomizer
                        .requestMatchers("/**").permitAll()
                        .anyRequest().authenticated()
                );

        return http.build();
    }

}

 

일단 SecurityConfig를 수정해주었다. 저번에는 비밀번호를 안전하게 저장하기 위한 해시화 기능만 있었다면, 이번엔 HTTP 기본 인증 비활성화, CSRF 보호 기능 비활성화 등 웹 애플리케이션의 기본적인 보안 설정을 추가해주었다.


Service

MemberService

로그아웃

    //로그아웃
    public void logout(HttpSession session) {
        if(session.getAttribute("member") != null) {
            session.removeAttribute("member");
            session.invalidate();
        }
    }

 

먼저, 세션에서 사용자가 로그인했을 때 설정된 "member" 속성이 존재하는지 확인한 후에 session.removeAttribute("member") 호출을 통해, 로그인 상태를 나타내는 "member" 속성을 세션에서 제거해 주었다. 이로써 사용자의 로그인 상태 정보가 세션에서 삭제되며, 사용자는 로그아웃 상태가 된다.  session.invalidate() 메소드 호출은 현재 세션을 완전히 무효화하는데, 이는 세션에 저장된 모든 속성을 제거하고, 세션을 종료하는 작업이다. 세션 무효화는 사용자의 로그아웃을 보다 확실하게 처리하기 위해 수행되며, 이후 같은 세션 ID로는 어떤 작업도 수행할 수 없게 한다.

 

원탈퇴

    //회원 탈퇴
    public void delete(Long memberId) {
        Member member = memberRepository.findById(memberId)
                .orElseThrow(() -> new IllegalArgumentException("회원을 찾을 수 없습니다."));
        memberRepository.delete(member);
    }

 

회원탈퇴는 먼저 memberId로 해당 멤버를 찾은 후에, 만약 회원을 찾을 수 없다고 하면 "회원을 찾을 수 없습니다"라는 예외를 반환한다.

회원 객체를 성공적으로 찾았다면, delete를 통해 해당 회원을 제거해준다.

 


Controller

MemberApiController

    //로그아웃
    @PostMapping("/user/logout")
    public ResponseEntity<String> logout(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        memberService.logout(session);
        return ResponseEntity.status(HttpStatus.OK).body("로그아웃 성공");
    }

 

로그아웃 컨트롤러는 현재 HTTP 요청과 연결된 세션을 가져오고, 해당 세션을 로그아웃 서비스에 전달하여 로그아웃 처리를 한다. 성공적으로 로그아웃이 완료되면, "로그아웃 성공" 메시지와 함께 HTTP 상태 코드 200(OK)을 응답한다.

 

    //회원탈퇴
    @DeleteMapping("/user/delete")
    public ResponseEntity<String> delete(HttpSession session){
        Member member = (Member) session.getAttribute("member");

        if (member != null){
            memberService.delete(member.getId());
            session.invalidate();
            return ResponseEntity.status(HttpStatus.OK).body("탈퇴 완료");
        } else {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
        }
    }

 

회원탈퇴는 먼저 세션에서 "member" 속성을 가져온 후 member가 있다면 (null이 아니라면), 회원탈퇴 서비스를 호출하여 해당 회원을 데이터베이스에서 삭제하고, 세션을 무효화한다. 만약 세션에 "member" 속성이 존재하지 않는다면 (즉, 사용자가 로그인 상태가 아니라면), HTTP 상태 코드 401(Unauthorized)과 함께 응답을 반환한다.

 


postman을 통한 데이터 확인

postman을 통해 데이터가 잘 넘어가는지 확인해주었다.

로그인 성공
로그아웃 성공
회원탈퇴 성공