지난 포스트 - 이메일 인증 코드 발송
https://velog.io/@icebox127/Spring-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EC%BD%94%EB%93%9C-%EB%B0%9C%EC%86%A1-%EA%B5%AC%ED%98%84
이메일 코드를 발송한 후, 어떻게 관리하는지에 대해 정리해보았다.
지난 번에는 랜덤 코드를 이메일로 보내는 것까지만 구현했는데, 여기에 이 이메일과 랜덤 코드를 저장하는 기능을 추가한다. 추후 사용자가 인증번호 확인 요청을 할 때 이를 대조하여야하기 때문이다.
EmailVerification.java
@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "email_verification")
public class EmailVerification {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "email", nullable = false)
private String email;
@Column(name = "code", nullable = false)
private String code;
@Column(name = "expire_date", nullable = false)
private LocalDateTime expireDate;
@Column(name = "verfied", nullable = false)
private boolean verified = false;
public void verify() {
this.verified = true;
}
public boolean isExpired() {
return LocalDateTime.now().isAfter(expireDate);
}
}
아이디, 사용자 이메일, 코드, 만기일시, 검증여부를 저장한다.
EmailCodeRepository.java
public interface EmailCodeRepository extends JpaRepository<EmailVerification, Long> {
Optional<EmailVerification> findByEmailAndCode(
String email, String verificationCode);
void deleteByEmail(String email);
}
앞서 만든 EmailVerification 엔터티를 조작할 리포지토리를 생성
이메일과 코드에 해당하는 값을 리턴할 findByEmailAndCode,
이전 값들을 지울 deleteByEmail 두 개의 메서드를 생성했다.
public void sendVerificationEmail(String emailTo, String type) {
String code = generateVerificationCode();
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
sendVerifyCode(emailTo, mimeMessage, code, type);
saveEmailVerifyCode(emailTo, code);
} catch (MessagingException e) {
throw new AuthException(AuthErrorCode.CODE_ERROR);
}
}
private void sendVerifyCode(String emailTo, MimeMessage mimeMessage, String code, String type) throws MessagingException {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");
mimeMessageHelper.setTo(emailTo);
mimeMessageHelper.setSubject("[TO:DAY] 이메일 인증 코드 발송");
mimeMessageHelper.setText(createHtmlEmailBody(code, type),true);
mimeMessageHelper.setFrom(fromEmail);
javaMailSender.send(mimeMessage);
}
private void saveEmailVerifyCode(String emailTo, String code) {
emailCodeRepository.deleteByEmail(emailTo);
EmailVerification ev = EmailVerification.builder()
.email(emailTo)
.code(code)
.expireDate(LocalDateTime.now().plusMinutes(10))
.build();
emailCodeRepository.save(ev);
}
지난 번 코드에 saveEmailVerifyCode를 추가한다.
+) 인증코드 전송 부분도 메소드를 추출해서 try문을 짧게 만들었다.
메소드 추출 단축키: Ctrl+ Alt + M
.expireDate(LocalDateTime.now().plusMinutes(10))
만료 시간은 10분으로 설정했다. (현재시간 + 10분)
db에 저장하는거라 데이터가 너무 많이 쌓일것을 고려하여, 새로운 코드를 발급받을 경우 해당 이메일이 발급받은 이전 코드는 전부 삭제하도록 하였다.
public void checkEmailVerifyCode(String email, String code){
EmailVerification ev = emailCodeRepository.findByEmailAndCode(email, code)
.orElseThrow(() -> new AuthException(AuthErrorCode.CODE_NOT_EXIST));
if (ev.isExpired()){
throw new AuthException(AuthErrorCode.CODE_EXPIRED);
}
ev.verify();
}
checkEmailVerifyCode를 따로 구현하였다.
만약 해당 이메일과 코드가 저장되어있지 않다면 (즉, 코드가 틀림) CODE_NOT_EXIST 에러를 발생 시킨다.
존재한다면, 만료여부를 확인하고 만료 시 CODE_EXPIRED 에러 발생시킨다.
만약 두 경우 다 아닐 시, verify = true로 인증을 성공시킨다.


받은 인증코드 47913으로 요청을 하니 성공적으로 처리되었다.