-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat : mail authentication add #86
Changes from all commits
dbebc52
c555672
2484449
dbc8839
506562a
a0da952
178ee53
8d7ee23
0b827b0
8bed1bf
b5ab1e8
29c34b8
ad8eb42
23dd94c
d4552da
b7222c4
564a749
4696525
66fb927
1973b96
31ba2c0
813dd59
317afb9
b40d221
f826eed
e2cd9a9
5e4495b
5eef4dd
41c4f41
d36b661
ac6d451
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.benchmarker.bmcontroller.common.beans; | ||
|
||
import org.benchmarker.bmcontroller.mail.common.strategy.IRandomCodeGenerator; | ||
import org.benchmarker.bmcontroller.mail.common.strategy.RandomCodeGenerator; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class RandomNumberConfig { | ||
@Bean | ||
public IRandomCodeGenerator randomNumber() { | ||
return new RandomCodeGenerator(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.benchmarker.bmcontroller.mail.common.factory; | ||
|
||
public interface EmailBodyGenerator { | ||
|
||
String createBody(String... args); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.benchmarker.bmcontroller.mail.common.factory; | ||
|
||
public class EmailVerificationFactory implements EmailBodyGenerator { | ||
|
||
@Override | ||
public String createBody(String... args) { | ||
|
||
String authNum = args[0]; | ||
|
||
return "안녕하세요!\n\n, 회원 가입을 위한 인증 코드를 안내드립니다. 아래의 인증 코드를 입력하여 계정을 활성화하세요:\n\n인증 코드: " + authNum; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package org.benchmarker.bmcontroller.mail.common.strategy; | ||
|
||
public interface IRandomCodeGenerator { | ||
|
||
String generateVerificationCode(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package org.benchmarker.bmcontroller.mail.common.strategy; | ||
|
||
import java.util.Random; | ||
|
||
public class RandomCodeGenerator implements IRandomCodeGenerator { | ||
|
||
private static final int CODE_LENGTH = 6; | ||
|
||
@Override | ||
public String generateVerificationCode() { | ||
|
||
Random random = new Random(); | ||
StringBuilder codeBuilder = new StringBuilder(); | ||
for (int i = 0; i < CODE_LENGTH; i++) { | ||
codeBuilder.append(random.nextInt(10)); | ||
} | ||
|
||
return codeBuilder.toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package org.benchmarker.bmcontroller.mail.controller; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpSession; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.benchmarker.bmcontroller.mail.common.factory.EmailBodyGenerator; | ||
import org.benchmarker.bmcontroller.mail.common.factory.EmailVerificationFactory; | ||
import org.benchmarker.bmcontroller.mail.controller.dto.*; | ||
import org.benchmarker.bmcontroller.mail.service.IMailSender; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.Objects; | ||
|
||
@Slf4j | ||
@RestController | ||
@RequestMapping("/api") | ||
@RequiredArgsConstructor | ||
public class MailController { | ||
|
||
private final IMailSender mailSender; | ||
|
||
@PostMapping("/mail/certification") | ||
public ResponseEntity<EmailResDto> mailSend(HttpServletRequest request, | ||
@Valid @RequestBody EmailCertificationDto emailCertification) { | ||
|
||
EmailBodyGenerator emailBodyGenerator = new EmailVerificationFactory(); | ||
EmailResDto mailResDto = mailSender.sendMail(emailCertification, emailBodyGenerator); | ||
|
||
HttpSession session = request.getSession(); | ||
|
||
UserSessionInfo userSessionInfo = UserSessionInfo.builder() | ||
.certificationCode(mailResDto.getCertificationCode()) | ||
.userMail(mailResDto.getMail()) | ||
.isVerification(false) | ||
.verificationTime(LocalDateTime.now()) | ||
.build(); | ||
|
||
session.setAttribute("userSessionInfo", userSessionInfo); | ||
|
||
log.info("Session data: {}", session.getAttribute("userSessionInfo").toString()); | ||
|
||
return ResponseEntity.ok(mailResDto); | ||
} | ||
|
||
@PostMapping("/mail/certification/code") | ||
public ResponseEntity<EmailCodeCertificationResultDto> certificationCode(HttpServletRequest request, | ||
@Valid @RequestBody EmailCodeDto emailCode) { | ||
|
||
HttpSession session = request.getSession(); | ||
UserSessionInfo userSessionInfo = (UserSessionInfo) session.getAttribute("userSessionInfo"); | ||
|
||
// 세션에 userSessionInfo가 존재하지 않을 때 | ||
if (userSessionInfo == null) { | ||
|
||
EmailCodeCertificationResultDto failRes = EmailCodeCertificationResultDto.builder() | ||
.status("fail") | ||
.message("Session expired or invalid. Please try again.") | ||
.build(); | ||
|
||
return ResponseEntity.ok(failRes); | ||
} else { | ||
if (!userSessionInfo.verificationCode(emailCode.getCode())) { | ||
|
||
EmailCodeCertificationResultDto failRes = EmailCodeCertificationResultDto.builder() | ||
.status("fail") | ||
.message("Please enter the authentication number correctly") | ||
.build(); | ||
|
||
return ResponseEntity.ok(failRes); | ||
} | ||
} | ||
|
||
EmailCodeCertificationResultDto successRes = EmailCodeCertificationResultDto.builder() | ||
.status("success") | ||
.message("Authentication successful!!") | ||
.build(); | ||
|
||
Objects.requireNonNull(userSessionInfo).changeStatus(); | ||
session.setAttribute("userSessionInfo", userSessionInfo); | ||
|
||
return ResponseEntity.ok(successRes); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package org.benchmarker.bmcontroller.mail.controller.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class EmailCertificationDto { | ||
|
||
@NotBlank | ||
@Pattern(regexp = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", message = "Please write in email format") | ||
private String email; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.benchmarker.bmcontroller.mail.controller.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class EmailCodeCertificationResultDto { | ||
|
||
private String status; | ||
|
||
private String message; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.benchmarker.bmcontroller.mail.controller.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class EmailCodeDto { | ||
|
||
@NotBlank | ||
private String code; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.benchmarker.bmcontroller.mail.controller.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class EmailResDto { | ||
|
||
private String mail; | ||
|
||
private String certificationCode; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package org.benchmarker.bmcontroller.mail.controller.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class UserSessionInfo { | ||
|
||
private String certificationCode; | ||
|
||
private String userMail; | ||
|
||
private boolean isVerification; | ||
|
||
private LocalDateTime verificationTime; | ||
|
||
private LocalDateTime updateTime; | ||
|
||
public boolean verificationCode(String code) { | ||
return this.certificationCode.equals(code); | ||
} | ||
|
||
public void changeStatus() { | ||
this.isVerification = !this.isVerification; | ||
this.updateTime = LocalDateTime.now(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isVerification 을 false -> true 로 설정해주는 것 외 true -> false 로도 설정하기 위해서 위와 같이 로직을 구현한걸까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금은 false -> true 설정만 필요하긴 한데 true -> false 설정이 필요한 일이 생길 수도 있지 않을까 해서 설정했습니다!! |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.benchmarker.bmcontroller.mail.service; | ||
|
||
import org.benchmarker.bmcontroller.mail.common.factory.EmailBodyGenerator; | ||
import org.benchmarker.bmcontroller.mail.controller.dto.EmailCertificationDto; | ||
import org.benchmarker.bmcontroller.mail.controller.dto.EmailResDto; | ||
|
||
public interface IMailSender { | ||
|
||
EmailResDto sendMail(EmailCertificationDto emailCertificationDto, EmailBodyGenerator emailBodyGenerator); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package org.benchmarker.bmcontroller.mail.service.impl; | ||
|
||
import jakarta.mail.MessagingException; | ||
import jakarta.mail.internet.MimeMessage; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.benchmarker.bmcontroller.mail.common.factory.EmailBodyGenerator; | ||
import org.benchmarker.bmcontroller.mail.controller.dto.EmailCertificationDto; | ||
import org.benchmarker.bmcontroller.mail.controller.dto.EmailResDto; | ||
import org.benchmarker.bmcontroller.mail.service.IMailSender; | ||
import org.benchmarker.bmcontroller.mail.common.strategy.IRandomCodeGenerator; | ||
import org.springframework.mail.javamail.JavaMailSender; | ||
import org.springframework.mail.javamail.MimeMessageHelper; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class MailSenderImpl implements IMailSender { | ||
|
||
private final JavaMailSender javaMailSender; | ||
|
||
private final IRandomCodeGenerator randomNumber; | ||
|
||
@Override | ||
public EmailResDto sendMail(EmailCertificationDto emailCertificationDto, EmailBodyGenerator emailBodyGenerator) { | ||
String authNum = randomNumber.generateVerificationCode(); | ||
|
||
String subject = "회원 가입 인증 코드"; | ||
String body = emailBodyGenerator.createBody(authNum); | ||
|
||
log.info("Start mail sender!!"); | ||
try { | ||
MimeMessage mimeMessage = javaMailSender.createMimeMessage(); | ||
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); | ||
mimeMessageHelper.setTo(emailCertificationDto.getEmail()); // 메일 수신자 | ||
mimeMessageHelper.setSubject(subject); // 메일 제목 | ||
mimeMessageHelper.setText(body, false); // 메일 본문 내용, HTML 여부 | ||
|
||
javaMailSender.send(mimeMessage); | ||
|
||
} catch (MessagingException e) { | ||
log.info("Mail sender fail!!"); | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return EmailResDto.builder() | ||
.mail(emailCertificationDto.getEmail()) | ||
.certificationCode(authNum) | ||
.build(); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미 상단에서 userSessionInfo 의 null 체크를 진행되어있지만, 한번 더 체크해주셔서 좋네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시 몰라서,,,, 2차 트랩을 설치 했습니다 ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋습니다ㅎㅎ