Spring Boot + React 프로젝트 / 이메일 전송 기능 (비밀번호 찾기, 임시비밀번호 부여)

fever·2024년 4월 9일
0

💻 구현 기능

  1. 이메일로 임시 비밀번호 전달하기
  2. 해당 비밀번호로 db 교체

✏️ 기능 설계

  1. 리액트에서 유저가 이메일과 전화번호를 입력 후 스프링부트로 전달
  2. db와 비교후 같으면 메일 서비스 실행
  3. 메일 서비스에서 임시 비밀번호 (난수) 생성
  4. 임시 비밀번호 해싱 후 db에 저장
  5. 메일 전달

📌 구현 과정

1. 구글 이메일 세팅

  • 앱 만들고, 해당 비밀번호 저장해두기

  • 만일, 앱 비밀번호 안 뜨면 2단계 인증을 진행해야 함


  • 메일로 들어가서 IMAP 설정 변경 (해당 구글 계정으로 이메일 발송 예정)

2. 리액트 세팅

  • 유저 객체 생성

  • 폼 설정

  • 함수 (지금은 submit만 적어놨는데, 인풋 입력값 set으로 넣어주는 함수도 필요함)

3. 스프링부트 세팅

  • 그래들 라이브러리 추가

3-1. application.properties

3-2. 인증 컨트롤러 (findPwd)

3-3. 인증 서비스 (findPwdByUser)

  • 비동기를 빼고 진행해도 작동은 되나, 3초정도 딜레이가 발생해서 비동기를 사용해주는 게 좋음

3-4. 메일 서비스 (MailSendService)

@Service
@RequiredArgsConstructor
public class MailSendService {
    // 이메일에 난수를 포함한 링크를 보내주는 서비스

    private final JavaMailSender mailSender;
    private final CertificationGenerator generator;

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder; // 스프링 시큐리티

    public void sendEmailForCertification(String email)
            throws NoSuchAlgorithmException, MessagingException {

        // 비밀번호 생성
        String certificationNumber = generator.createCertificationNumber();

        String img = "<img src='이미지주소'/>";
        String link = "<a href='http://localhost:3000/login'>로그인 링크</a>";

        String content = String.format("%s <br> 임시비밀번호: %s <br><br> %s <br> 로그인 후 마이페이지에서 비밀번호를 수정해주세요.",
                img,
                certificationNumber,
                link);

        // 비밀번호 해싱
        String userPw = passwordEncoder.encode(certificationNumber);

        // DB에 비밀번호 저장
        Optional<UserEntity> optionalUser = userRepository.findByUserEmail(email);
        if (optionalUser.isPresent()) {
            UserEntity user = optionalUser.get();
            user.setUserPw(userPw); // 비밀번호 설정
            userRepository.save(user); // 변경된 비밀번호를 DB 저장
        }

        // 이메일 전송
        sendMail(email, content);
    }

    private void sendMail(String email, String content) throws MessagingException {

        // 이메일 객체 생성
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);

        // 수신자, 제목, 내용 설정
        helper.setTo(email);
        helper.setSubject("AriQ 비밀번호 변경 메일");
        helper.setText(content, true); // html변환 전달

        // 메일 전송
        mailSender.send(mimeMessage);
    }
}

3-5. 난수 생성 클래스 (CertificationGenerator)

@Component
public class CertificationGenerator {
    // 영문 알파벳
    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public String createCertificationNumber() throws NoSuchAlgorithmException {
        StringBuilder result = new StringBuilder();

        // 영어 알파벳과 숫자를 조합하여 난수 생성
        do {
            // 10자리의 난수 생성
            for (int i = 0; i < 10; i++) {
                // SecureRandom을 이용하여 0부터 35 사이의 난수 생성
                int randomIndex = SecureRandom.getInstanceStrong().nextInt(ALPHABET.length() + 10);

                // 숫자인 경우
                if (randomIndex < 10) {
                    result.append(randomIndex);
                }
                // 알파벳인 경우
                else {
                    // ALPHABET 문자열에서 랜덤한 영문 알파벳 선택하여 결과 추가
                    result.append(ALPHABET.charAt(randomIndex - 10));
                }
            }
        } while (result.length() != 10);

        return result.toString();
    }

}

4. 결과

  • 이메일도 잘 오고, 해당 번호로도 로그인이 가능

🤔 다음 목표와 고민들

  1. 회원가입시 이메일 인증 기능 추가
    -레디스 사용해서 난수를 저장 후, 이메일로 보낸 번호와 같으면 회원가입 실행
  2. 비밀번호 찾기를 링크로 인증
    -레디스 사용해서 난수를 저장 후, 이메일로 난수와 링크가 담긴 url 보내기
    -해당 링크 받아서 레디스와 비교후 동일하면, 마이페이지 정보 수정창으로 이동
  3. 예외처리 하기! (지금 너무 무대포로 404와 에러 코드만 보내고 있음 ㅎ;)
profile
선명한 삶을 살기 위하여

0개의 댓글