시나리오
1. 이메일 인증 버튼 클릭
→ 인증 코드를 발급함과 동시에 인증(Auth) 테이블에 이메일과 인증코드를 저장
2. 이메일과 인증 코드로 인증 확인 요청
3. 인증(Auth) 테이블에 저장된 이메일이 있는 지 확인
→ 없으면 인증 실패
4. 인증 테이블에 저장된 이메일과 인증 코드가 맞는 지 확인
→ 맞으면 인증 성공
→ 틀리면 인증 실패
Auth Entity
@Entity
@Getter
@NoArgsConstructor
public class Auth {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String authCode;
public Auth(String email, String authCode){
this.email = email;
this.authCode = authCode;
}
public void patch(String authCode){
this.authCode = authCode;
}
}
MailService 코드 수정
- 이전 글에서는 true 또는 false를 반환하였으나, 인증 코드를 저장하기 위해 String 인증 코드를 반환
public String sendSimpleMessage(String sendEmail) throws MessagingException {
String authCode = createCode(); // 랜덤 인증번호 생성
MimeMessage message = createMail(sendEmail, authCode); // 메일 생성
try {
javaMailSender.send(message); // 메일 발송
return authCode;
} catch (MailException e) {
return null;
}
}
MemberService 코드 수정 및 추가
- 이전 글에서는 MemberController에서 MailService를 사용하여 발급 처리
- 하지만, 발급된 인증 코드를 이용한 비즈니스 로직이 필요하기 때문에 MeberService에서 처리하도록 변경
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final MailService mailService;
private final AuthRepository authRepository;
(생략)
@Transactional
public boolean sendAuthcode(String email) throws MessagingException {
String authCode = mailService.sendSimpleMessage(email);
if(authCode != null){
Auth auth = authRepository.findByEmail(email);
if(auth == null)
authRepository.save(new Auth(email, authCode));
else
auth.patch(authCode);
return true;
}
return false;
}
public boolean validationAuthcode(String email, String authCode) {
Auth auth = authRepository.findByEmail(email);
if(auth != null && auth.getAuthCode().equals(authCode)){
authRepository.delete(auth);
return true;
}
return false;
}
}
sendAuthcode()
- 인증 코드를 발급하는 메서드
- Auth 테이블에 입력한 이메일이 존재하는 지 확인
- 처음 인증 코드를 발급 받는 것이라면 테이블에 저장
- 발급 받은 적이 있다면 가장 마지막의 인증 코드로만 인증이 될 수 있도록 업데이트 필요
→ @Transactional 어노테이션을 사용함으로써 DB에서 가져온 auth를 영속성 컨텍스트에 등록하여 Dirty Check 가능
즉, auth.patch()로 변화가 일어난 것을 감지하여 메서드 종료 시 자동으로 update query문이 발생 됨
validationAuthcode()
- 이메일과 인증 코드를 검증하는 메서드
- 사용자가 입력한 Email과 인증 코드가 완전히 일치하는 지 확인
→ 일치하다면 인증 테이블에서 삭제하고 인증 성공 처리 - 그 외 (입력한 이메일이 인증 코드를 발급 받지 않았거나, 인증 코드가 일치하지 않는 경우)
→ 인증 실패 처리
MemberController
@RestController
@RequestMapping("/api/member")
@RequiredArgsConstructor
@Slf4j(topic = "MemberController")
public class MemberController {
private final MemberService memberService;
(생략)
@GetMapping("/email/auth/{email}")
public ResponseEntity<String> requestAuthcode(@PathVariable String email) throws MessagingException {
boolean isSend = memberService.sendAuthcode(email);
return isSend ? ResponseEntity.status(HttpStatus.OK).body("인증 코드가 전송되었습니다.") :
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("인증 코드 전송이 실패하였습니다.");
}
@PostMapping("/email/auth")
public ResponseEntity<String> validateAuthcode(@RequestParam(name = "email")String email,
@RequestParam(name = "auth")String authCode) {
boolean isSuccess = memberService.validationAuthcode(email, authCode);
return isSuccess ? ResponseEntity.status(HttpStatus.OK).body("이메일 인증에 성공하였습니다.") :
ResponseEntity.status(HttpStatus.BAD_REQUEST).body("이메일 인증에 실패하였습니다.");
}
}
Postman을 이용한 테스트
- 인증코드 발급 1회 시도
- 인증코드 발급 2회 시도 + 영속성 컨텍스트 Dirty Check
- 인증 코드 확인
'Language > Spring' 카테고리의 다른 글
[Spring Boot] Redis를 이용한 이메일 인증 리팩토링 (0) | 2024.08.13 |
---|---|
레디스(Redis) 개념 및 설치 (0) | 2024.08.13 |
[Spring Boot] 구글 이메일 인증 코드 발급 구현 (0) | 2024.08.13 |
JpaAuditing 사용 방법 및 예제 (0) | 2024.08.12 |
BeanFactory, ApplicationContext (0) | 2024.08.10 |