gi_dor

회원탈퇴 - SpringSecurity, MySQL , MyBatis 본문

Back_End/SpringBoot

회원탈퇴 - SpringSecurity, MySQL , MyBatis

기돌 2024. 4. 22. 15:13
728x90
ON DELETE CASCADE  설정  ?

 

Delete Cascade 는  부모 테이블의 행이 삭제될 때  연관된 자식 테이블의 행이 자동으로 삭제되는 기능
외래 키(Foreign Key) 관계에 적용되는 경우가 많다

예를 들어, 사용자(User)와 그 사용자가 작성한 댓글(Comment)이라는 두 개의 테이블이 있다면.

댓글 테이블은 사용자 테이블을 참조하는 외래 키 FK 를 가지고 있습니다.
이 때, delete Cascade가 설정되어 있다면 사용자 테이블의 특정 사용자의 행이 삭제되면 그 사용자가 작성한
모든 댓글 또한 자동으로 삭제됩니다.

delete Cascade 는 데이터 일관성을 유지하는 데 도움이 될 수 있지만 주의해야 할게 있습니다

예를 들어, 부모 테이블의 레코드를 실수로 삭제했을 때 그와 연관된 모든 자식 레코드가 함께 삭제되므로
데이터의 손실이 발생할 수 있습니다.
또한, delete Cascade 는 대규모 데이터베이스에서 사용할 때 성능 문제를 발생할 수 있습니다

 

이것을 방치하고자 회원 테이블에 사용자를 on delete cascade 설정하지 않고 String userDelYn 을 사용 하겠습니다.

 

테이블에 컬럼 설정에  Default 값을 'N' 으로 설정하겠습니다

 

 


 

 <!-- 회원탈퇴 -->
    <update id="deleteUserById" parameterType="string">
        UPDATE USER
        SET user_del_yn = 'Y'
        WHERE user_id = #{id}
    </update>
<select id="selectUserById" parameterType="string" resultType="com.example.bookhub.user.vo.User">
        SELECT
               u.user_no              as no,
               u.user_id              as id,
               u.user_password        as password,
               u.user_name            as name,
               u.user_email           as email ,
               u.user_tel             as tel ,
               u.user_zip_code        as zipCode ,
               u.user_address         as address ,
               u.user_address_detail  as addressDetail ,
               u.user_created_date    as createdDate,
               u.user_updated_date    as updatedDate ,
               u.user_del_yn          as delYn ,
               u.user_point           as point,
               g.grade_no             as "userGrade.no",
               g.grade_name           as "userGrade.name"
        FROM USER u , USER_GRADE g
        WHERE user_id = #{id}
        and u.grade_no = g.grade_no
    </select>

 

@Mapper
public interface MyPageMapper {
	void deleteUserById(String id);
}

 

 public void deleteUserById(String id, String password) {
            // 사용자 아이디로 정보 가져오기
            User user =  userService.selectUserById(id);

            // 사용자가 입력한 비밀번호를 암호화하여 검증
            if (passwordEncoder.matches(password, user.getPassword())) {
                // deletedYn 'N' -> 'Y'
                myPageMapper.deleteUserById(user.getId());
            } else {
                throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
            }
        }

 

(passwordEncoder.matches(password, user.getPassword()))

사용자가 입력한 비밀번호와 데이터베이스에 저장된 암호화된 비밀번호를 비교합니다.

비밀번호 비교 후 일치 한다면 deletedYn 의 값을 'Y' 으로

 

@GetMapping("/deleteForm")
    public String deleteForm(Model model , Principal principal ) {

        String userId = principal.getName();
        User user = userService.selectUserById(userId);

        model.addAttribute("user",user);

        return "user/deleteUserForm";
    }

    @PostMapping("/deleteUser")
    public String deleteAccount(Principal principal , String password) {

        try{
            // 사용자 탈퇴 처리
            myPageService.deleteUserById(principal.getName(), password);
            // 로그아웃
            return "redirect:/user/logout";

        } catch (IllegalArgumentException ex) {
            return "redirect:/mypage/deleteForm?error"; // 비밀번호 오류 페이지로 리다이렉트
        }

    }

 

   return "redirect:/user/logout"; 

//SpringConfig

http.logout(logout -> logout.logoutUrl("/user/logout")
                    .logoutSuccessUrl("/").invalidateHttpSession(true));

 

 

confirm 안내문

form 태그내에 button 태그의 type을 submit 이 아닌 button 으로 변경후 Javascript 코드를 추가하겠습니다

<form method="post" action="/mypage/deleteUser" id="deleteUserForm">
	<input type="text" class="form-control" th:value="${user.id}" th:name="id" readonly/>
    <input type="password" class="form-control" id="password" th:name="password"  />
</form>

<script  layout:fragment="script">
  function confirmDelete() {
        let result = confirm("회원 탈퇴를 진행하시겠습니까?");
        if (result) {
            document.getElementById("deleteUserForm").submit();
        }
    }
</script>

 

비밀번호 일치 하지 않을 때

 

let urlSearch = new URLSearchParams(location.search);
if (urlSearch.has("error")) {
    alert(" 비밀번호가 올바르지 않습니다.");
}

 

https://developer.mozilla.org/ko/docs/Web/API/URLSearchParams

 

URLSearchParams - Web API | MDN

URLSearchParams 인터페이스는 URL의 쿼리 문자열을 대상으로 작업할 수 있는 유틸리티 메서드를 정의합니다.

developer.mozilla.org

 

https://sentry.io/answers/how-to-get-values-from-urls-in-javascript/

 

How to get values from URLs in JavaScript

The Problem You have a URL with parameters, which are known as query string parameters. For example, your query string may have a type, page, and sort parameter…

sentry.io

 

 

 

 

 


 

  @Override
    public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {

        // 사용자 아이디를 기준으로 데이터베이스에서 사용자 정보를 가져옵니다. 이 정보는 user 객체에 저장
        User user = userMapper.selectUserById(id);

        // 데이터베이스에서 가져온 사용자 정보가 없다면(null이면) 예외를 발생시킵니다.
        if(user == null) {
            throw new UsernameNotFoundException("등록되지 않은 사용자이거나 탈퇴처리된 사용자입니다. : " +id);
        }

        if ("Y".equals(user.getDelYn())) {
            throw new UsernameNotFoundException("회원탈퇴 처리된 계정입니다 : " +id);
        }


        // UserDetailsImpl 클래스의 객체를 생성합니다. 이 객체는 사용자의 인증 및 권한 정보를 제공하기위해 사용한다
        UserDetailsImpl userDetails = new UserDetailsImpl();

        // 객체에서 가져온 사용자 아이디와 비밀번호를 userDetails 객체에 설정
        userDetails.setId(user.getId());
        userDetails.setPassword(user.getPassword());

        userDetails.setAuthorities(List.of(new SimpleGrantedAuthority("ROLE_USER")));

        System.out.println("로그인한 아이디 : " +user.getId());
        return userDetails;
    }

 

728x90