본문 바로가기
카테고리 없음

Member 부분 구현해보자-4 (delete, 비밀번호찾기, 임시비밀번호 이메일)

by 티코딩 2024. 2. 27.

이제 Member 에 남은 api는 삭제, 로그인, 리프레시 토큰 발급, 비밀번호 찾기 인증번호 검증 후 이메일로전송

이렇게 남았다.

삭제랑 이메일관련은 쉽다.

로그인,리프레시 토큰 재발급 api는 JWT를 사용할것이다. 

먼저 이번 포스팅에는 삭제와 이메일관련 api부터 구현해보자.

 

ㅇ Service - deleteMember

public void deleteMember(Long memberId) {
        Member existMember = memberRepository.findById(memberId)
                .orElseThrow(()-> new EntityNotFoundException("사용차를 찾을 수 없습니다."));
        memberRepository.delete(existMember);
    }

 

ㅇ Controller - deleteMember

@DeleteMapping("/{member-id}")
    public ResponseEntity<?> deleteMember(@PathVariable("member-id") Long memberId) {
        memberService.deleteMember(memberId);
        return ResponseEntity.ok("회원삭제가 완료되었습니다.");
    }

 

ㅇ 테스트

 

쉽다. 원래는 lastLoggedIn 해서 스케줄러를 돌려서 기준을 정하고 그 기준에 미달할만큼 로그인하지않았다면, 휴면회원처리를 하는게 맞다. 하지만 일단은 기능구현부터 해야해서 이렇게 간단히 구현했다. 다음으로 비밀번호 찾기 로직을 구현해보자.

 

 

먼저 비밀번호를 찾기위해 이메일인증을 다시해야한다. signup에서 사용했던 sendEmail을 재사용하면 된다.

ㅇ Service - sendEmail

public void sendEmail(String recipientEmail, String subject) throws MessagingException {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(recipientEmail);
            helper.setSubject(subject);
            String randomKey = generateRandomKey(7);
            // EmailConfirmRandomKey 저장
            EmailConfirmRandomKey confirmRandomKey = EmailConfirmRandomKey.builder()
                    .email(recipientEmail)
                    .randomKey(randomKey)
                    .build();
            emailConfirmRandomKeyRepository.save(confirmRandomKey);
            // 이메일 템플릿 불러오기
            String emailTemplate = getEmailTemplate(recipientEmail, randomKey);
            helper.setText(emailTemplate, true);

            javaMailSender.send(message);
            System.out.println("Email Template: " + emailTemplate);
        } catch (MessagingException e) {
            // 예외 처리 로직 작성
            e.printStackTrace(); // 예외 내용을 콘솔에 출력하거나 로깅할 수 있습니다.
            // 예외 처리 후 필요한 작업 수행
        }
    }

이건 그대로 사용하면되고,

ㅇ Controller - findPw

@PostMapping("/password")
    public ResponseEntity<?> findPw(@RequestBody MemberDto.PasswordFind requestBody) {
        String subject = "비밀번호 찾기용 랜덤키를 발송합니다.";
        try {
            memberService.sendEmail(requestBody.getEmail(), subject);
            return ResponseEntity.ok("이메일이 성공적으로 발송되었습니다.");
        } catch (MessagingException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("이메일 발송에 실패했습니다.");
        }
    }

일단 제목만 바꿔서 보냈다.

메일본문을 바꾸려면 새로 HTML 파일을 만들어야하는데 귀찮아서 그냥 재사용했다.

 

ㅇ 테스트

잘 도착하는걸 볼 수 있다.

 

ㅇ Service - verifyAndSend

패스워드를 담아보내려면 다시 디코딩해야하는데 안된다고 한다. 그래서 임시 비밀번호를 생성해서 보내주기로 했다. 그리고 사용자가 패스워드변경을 할 수 있게 만들어줘야 했다.

일단 임시 비밀번호를 생성하는 메서드와, 인증번호를 검증하고 임시 비밀번호를 생성해서 이메일로 보내주는 서비스로직을 짜봤다.

앞에서 사용한 코드들을 짬뽕해서 사용한거다.

public void verifyAndSend(String randomKey, String email) {
		//이메일 검증
        EmailConfirmRandomKey emailConfirmRandomKey = emailConfirmRandomKeyRepository.findByEmail(email)
                .orElseThrow(() -> new IllegalStateException("유효하지 않은 이메일입니다."));
        String newRandomKey = emailConfirmRandomKey.getRandomKey();
		//비밀번호 인증용랜덤키를 검증
        if(!randomKey.equals(newRandomKey)){
            throw new IllegalArgumentException("인증코드가 유효하지 않습니다.");
        }
        Optional<Member> existingMember = memberRepository.findByEmail(email);
        //임시 비밀번호를 생성
        String tempPw = generateTempPw(10);
        if(existingMember.isPresent()){
            Member member = existingMember.get();
            //임시비밀번호를 인코딩
            String encodedTempPw = passwordEncoder.encode(tempPw);
            //인코딩한 임시비밀번호를 DB에 저장.
            member.setPassword(encodedTempPw);
            memberRepository.save(member);
            try {
                String subject = "[shopppingmall] 임시 비밀번호를 보내드립니다.";
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true);
                helper.setTo(member.getEmail());
                helper.setSubject(subject);
                // 이메일 템플릿 불러오기
                String pwTemplate = getPasswordTemplate(member.getEmail(), tempPw);
                helper.setText(pwTemplate, true);

                javaMailSender.send(message);
                System.out.println("Email Template: " + emailTemplate);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
        //인증용랜덤키 삭제
        emailConfirmRandomKeyRepository.deleteById(email);
    }

public String generateTempPw(int keyLength) {
		//특수기호까지 추가
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%";
        StringBuilder randomKey = new StringBuilder();

        SecureRandom secureRandom = new SecureRandom();
        for (int i = 0; i < keyLength; i++) {
            int randomIndex = secureRandom.nextInt(characters.length());
            randomKey.append(characters.charAt(randomIndex));
        }

        return randomKey.toString();
    }

//패스워드 템플릿
public String getPasswordTemplate(String recipientEmail, String tempPw) {
        try {
            // Create the Thymeleaf context and set variables
            Context context = new Context();
            context.setVariable("recipientEmail", recipientEmail);
            context.setVariable("tempPw", tempPw);

            // Process the email template using the template engine
            String emailTemplate = templateEngine.process("pw_template", context);

            return emailTemplate;
        } catch (Exception e) {
            throw new RuntimeException("Failed to process email template.", e);
        }
    }

 

ㅇ resources-pw_template.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title> 고객님의 임시 비밀번호를 보내드립니다.</title>
</head>
<body>
<h1>Welcome!</h1>
<p>밑의 비밀번호를 복사해서 로그인 후, 비밀번호 변경을 하세요.</p>
<p>임시 비밀번호: <span th:text="${tempPw}"></span></p>
</body>
</html>

Controller - confirmFindPw

@PostMapping("/confirm-pw")
    public ResponseEntity<?> confirmFindPw(@RequestBody MemberDto.Verify requestBody) {
        try{
            memberService.verifyAndSend(requestBody.getRandomKey(), requestBody.getEmail());
            return ResponseEntity.ok("이메일로 임시비밀번호를 전송했습니다.");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("인증 처리중 오류가 발생했습니다.");
        }
    }

 

ㅇ 테스트

 

겨우 했다. 다음 포스팅에는 JWT를 다루는 로그인, 리프레시토큰 재발급을 해보도록 하겠다.