-
회원가입 이메일 인증
-
인증메일 발송 JavaMailSender
-
인증 토큰값 확인
-
@Profile("local") // 로컬일때 이 bean이 등록되도록
@Component
@Slf4j
public class ConsoleMailSender implements JavaMailSender {
// 콘솔로 출력하는 형태로 임시로 구현. 추후 변경
@Override
public MimeMessage createMimeMessage() {
return null;
}
@Override
public MimeMessage createMimeMessage(InputStream inputStream) throws MailException {
return null;
}
@Override
public void send(MimeMessage mimeMessage) throws MailException {
}
@Override
public void send(MimeMessage... mimeMessages) throws MailException {
}
@Override
public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException {
}
@Override
public void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException {
}
@Override
public void send(SimpleMailMessage simpleMailMessage) throws MailException {
log.info(simpleMailMessage.getText());
}
@Override
public void send(SimpleMailMessage... simpleMailMessages) throws MailException {
}
}
이메일 전송 기능을 위해 JavaMailSender 를 구현한다.
임의로 콘솔로 출력하는 형태로 작성하였으며, local에서만 실행되도록 한다.
@Slf4j 를 이용하여 발송시 로그를 확인 할 수 있도록 한다.
// AccountController.java
@PostMapping("/sign-up") // JSR-303 Valid 검사
public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors) {
if (errors.hasErrors()) {
return "account/sign-up"; //에러가 있으면 다시 폼으로
}
accountService.processNewAccount(signUpForm);
return "redirect:/";
}
@Service
@RequiredArgsConstructor
public class AccountService {
private final AccountRepository accountRepository;
private final JavaMailSender javaMailSender;
private final PasswordEncoder passwordEncoder;
@Transactional
public void processNewAccount(SignUpForm signUpForm) {
Account newAccount = saveNewAccount(signUpForm); // 새로운 Account 생성
newAccount.generateEmailCheckToken(); // 이메일 체크 토큰 생성
// saveNewAccount 후에 detached 상태가 되기 때문에 토큰값이 저장이 안됨
// persist 상태 유지를 위해 @Transactional 을 붙여야 함
sendSignUpConfirmEmail(newAccount); // 이메일 전송
}
private Account saveNewAccount(@Valid SignUpForm signUpForm) {
Account account = Account.builder()
.email(signUpForm.getEmail())
.nickname(signUpForm.getNickname())
.password(passwordEncoder.encode(signUpForm.getPassword()))
.studyCreatedByWeb(true)
.studyEnrollmentResultByWeb(true)
.studyUpdatedByWeb(true)
.build();
return accountRepository.save(account);
}
private void sendSignUpConfirmEmail(Account newAccount) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(newAccount.getEmail());
mailMessage.setSubject("StudyNy, 회원 가입 인증");
mailMessage.setText("/check-email-token?token=" + newAccount.getEmailCheckToken() +
"&email=" + newAccount.getEmail());
javaMailSender.send(mailMessage);
}
}
// Account.java
public void generateEmailCheckToken() {
this.emailCheckToken = UUID.randomUUID().toString(); // 랜덤 UUID 사용
}
sign-up요청이 들어오면 새로운 Account 생성 후 이메일 체크 토큰값을 생성한다.
UUID를 이용하여 랜덤한 토큰 값을 생성하였으며, 이 토큰값과 함께 이메일을 전송하게 된다.
saveNewAccount 후에 detached 상태가 되기 때문에 persist 상태 유지를 위해 @Transactional 를 붙여줘야 한다.
// AccountController.java
// 인증메일 확인
@GetMapping("/check-email-token")
public String checkEmailToken(String token, String email, Model model) {
Account account = accountRepository.findByEmail(email);
String view = "account/checked-email";
if (account == null) {
model.addAttribute("error", "wrong.email");
return view;
}
if (!account.getEmailCheckToken().equals(token)) {
model.addAttribute("error", "wrong.token");
return view;
}
account.completeSignUp();
/* account.setEmailVerified(true); 리팩토링 - Account로 이동
account.setJoinedAt(LocalDateTime.now()); */
model.addAttribute("numberOfUser", accountRepository.count());
model.addAttribute("nickname", account.getNickname());
return view;
}
인증메일 확인을 하는 요청도 구현한다. 토큰 값을 받아 디비에 저장되어 있는 토큰값과 같은지 확인한다.
'Study > Spring JPA' 카테고리의 다른 글
[스프링 JPA] 현재 인증된 사용자 정보 참조 (0) | 2021.01.24 |
---|---|
[스프링 JPA] 회원가입 - 가입 완료 후 자동 로그인 (0) | 2021.01.24 |
[스프링 JPA] 회원가입 - 패스워드 인코더 (0) | 2021.01.17 |
[스프링 JPA] 회원가입 - 테스트 코드 및 시큐리티 설정 (0) | 2021.01.17 |
[스프링 JPA] 회원가입 폼 검증 (0) | 2021.01.17 |