일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 컴파일
- 인터프린터언어
- java list 저장
- java최솟값구하기
- java알고리즘
- java map 출력
- 노베이스부트캠프
- 코딩부트캠프후기
- javaJVM
- 프로그래머스제일작은수
- 격파르타장점
- java set 출력
- 격파르타비전공자
- 항해99후기
- 프로그래머스
- 격파르타후기
- 격파르타합격후기
- 작은수제거하기
- java참조자료형
- javaJRE
- java map
- 항해15기
- java set 저장
- java 자료구조 활용
- 비전공자sqld
- sqld자격증합격
- java기본자료형
- java list 출력
- java map 저장
- java알고리즘문제풀이
- Today
- Total
코딩과 결혼합니다
[Game_Crew] 리팩토링 + 트러블슈팅 : 이메일 인증 코드 리팩토링 본문
📌 [ 이메일 중복확인 API ]와 [ 이메일 인증 코드 발송 API ] 합치기
- 사용자의 무분별한 계정 등록을 방지하기 위하여 인증 번호를 받을 수 있는 이메일을 입력하도록 유도
- 이메일을 입력하면 중복체크를 먼저 진행
- 중복되지 않았다면 "사용할 수 있는 이메일입니다."와 같은 메시지와 인증 code 번호를 프런트에 반환
//이메일 중복확인 및 인증코드 전송
@PostMapping("/signup/email")
public MessageResponseDto checkAndSendEmail(@RequestBody @Valid CheckEmailRequestDto requestDto) {
String authCode = signupService.checkAndSendEmail(requestDto.getEmail());
return new MessageResponseDto(Message.AVAILABLE_EMAIL + "인증 코드: " + authCode, HttpStatus.OK);
}
//이메일 중복 확인 및 인증코드 전송
public String checkAndSendEmail(String email) {
Optional<User> checkEmail = userRepository.findByEmail(email);
if (checkEmail.isPresent()) {
throw new CustomException(ErrorMessage.DUPLICATE_EMAIL_EXISTS, HttpStatus.CONFLICT, true);
}
// 중복되는 이메일이 없으면 인증 코드 발송
try{
return sendSimpleMessage(email);
}catch(Exception e){
throw new CustomException(ErrorMessage.FAILED_TO_SEND_EMAIL, HttpStatus.INTERNAL_SERVER_ERROR, true);
}
}
📌 Auth의 EmailControll, EmailService➡️ User 패키지의 SignUpController와 SignUpService에 합침
- 관련 api 끼리 합침으로 auth domin 삭제(필요시에 다시 만들겠음)
- LoginRequestDto의 경우 filter 단에서 처리하고 있으므로 global 패키지에 request 하위 패키지 생성 후 그곳으로 옮김
이렇게 함으로써 이전의 URL에 이메일 주소가 그대로 드러나 보안적으로 문제가 있는 점이 해결되었다.
https://coding-s2-chaewon.tistory.com/195
[Game_Crew] 트러블슈팅 : 이메일 인증 완성
문제 jakarta.mail.MessagingException: Could not connect to SMTP host: smtp.naver.com, port: 587; 메일 서버 연결에 실패. SMTP 호스트 smtp.naver.com의 587에 연결할 수 없다는 내용이다. javax.net.ssl.SSLException: Unsupported or unre
coding-s2-chaewon.tistory.com
파싱 문제는 RequestDto를 통해 데이터를 받아 사용함으로 해결할 수 있었다.
😎트러블 슈팅
문제 이메일 중복확인 후에 받은 인증 코드를 입력했을 때 결괏값으로 계속해서 false가 나왔다.
이유
@PostMapping("/signup/email/check")
@ResponseBody
public boolean verifyCode(@RequestBody CodeRequestDto code){
boolean isVerified = code.equals(signupService.getEPw());
return isVerified;
}
equals() 메서드가 CodeRequestDto 클래스에 정의되어 있지만, 이 메서드는 CodeRequestDto 인스턴스 자체를 비교하고 있다. 즉, code는 CodeRequestDto 객체이고, 이 객체와 문자열인 signupService.getEPw()를 비교하려 하기 때문에 항상 false가 반환되는 것이다.
해결
boolean isVerified = code.getCode().equals(signupService.getEPw());
getCode() 메서드를 사용하여 실제 인증 코드 문자열을 가져와 서비스에서 반환된 인증 코드와 비교한다.
😎트러블 슈팅(2)
이러한 의문점이 생겼다.
- 사용자가 동시에 인증 코드를 받고 입력한 경우 서버는 어떻게 각 사용자의 코드인지 구분할 수 있나?
- 여러 요청이 동시에 접근했을 때 이 동시성 문제를 해결하기 위해 어떠한 행동을 취해야 하는가?
- 인증 코드와 email 주소를 DB에 저장해 놓고 비교한 뒤에 사용한 인증코드는 어떻게 삭제해야 할까?
해결
//이메일 중복확인 및 인증코드 전송
@PostMapping("/signup/email")
public MessageResponseDto checkAndSendEmail(@RequestBody @Valid CheckEmailRequestDto requestDto) {
String authCode = signupService.checkAndSendEmail(requestDto.getEmail());
Auth auth = new Auth(requestDto.getEmail(), authCode);
authRepository.save(auth);
return new MessageResponseDto(Message.AVAILABLE_EMAIL + "인증 코드: " + authCode, HttpStatus.OK);
}
사용할 수 있는 이메일이면 그 이메일 주소와 code를 db에 저장한다.
@PostMapping("/signup/email/check")
@ResponseBody
public MessageResponseDto verifyCode(@RequestBody EmailCodeRequestDto requestDto){
return signupService.verifyCode(requestDto.getEmail(), requestDto.getCode());
}
다음 프런트로부터 받은 입력값과 비교하여 이메일과 코드가 일치하는지 확인한다. 이렇게 여러 개의 요청이 동시에 오더라도 구분될 수 있게 구현하였다.
1,2번은 해결하였으나 3번의 경우에는 우선적으로 MVP기능을 모두 구현한 다음에 시도해 볼 것이다!
😎트러블 슈팅(3) - 인증코드가 랜덤값이 아닌 같은 값으로만 발송된다.
Duplicate entry '800182' for key 'auth.UK_nn8juweilrld7bkd9qfwjrvxx'
인증코드가 계속해서 '800182'로만 보내지고 code에 unique를 걸어놨기에 중복된 값을 가지고 접근하려 하여 계속해서 오류가 발생했다.
@Column(nullable = false)
private String code;
먼저 인증코드가 랜덤으로 만들어지기는 하나 혹여나 같은 값을 낼 수 도 있으니 unique 한 값이 아니어도 허용할 수 있게 하였으며, 계속해서 같은 값을 반환하는 문제를 해결하기 위하여 코드의 로직을 뜯어보았다.
public String checkAndSendEmail(String email) {
//...
// 중복되는 이메일이 없으면 인증 코드 발송
try{
return sendSimpleMessage(email);
}catch(Exception e){
throw new CustomException(ErrorMessage.FAILED_TO_SEND_EMAIL, HttpStatus.INTERNAL_SERVER_ERROR, true);
}
}
public MessageResponseDto verifyCode(String email, String code) {
//이메일과 코드 일치하는지 체크하는 메서드
}
private final String ePw = createKey();
public MimeMessage createMessage(String to)throws MessagingException, UnsupportedEncodingException {
log.info("보내는 대상 : "+ to);
log.info("인증 번호 : " + ePw);
//메일 양식과 전송관련 설정 메서드
}
public static String createKey() {
//랜덤한 인증코드를 반환하는 메서드
}
public String sendSimpleMessage(String to)throws Exception {
//메일 발송 관련 메서드, 메일로 보냈던 인증 코드를 서버로 리턴
return ePw;
}
이전 코드 같은 경우에는 ePw 변수가 createMessage() 메서드와 sendSimplieMessage() 메서드 사이에 위치해 있어서 같은 코드 값을 반환하는 현상이 발생하였다. ePw 변수를 전역 변수로 선언하고 createKey() 메서드를 통해 한 번만 생성한 후, 이 값을 계속 사용하였기 때문이다.
public MimeMessage createMessage(String to)throws MessagingException, UnsupportedEncodingException {
log.info("보내는 대상 : "+ to);
log.info("인증 번호 : " + ePw);
//메일 양식과 전송관련 설정 메서드
}
public String sendSimpleMessage(String to)throws Exception {
// 인증코드 생성 이동
String ePw = createKey();
MimeMessage message = createMessage(to, ePw);
try{
javaMailSender.send(message); // 메일 발송
}catch(MailException es){
es.printStackTrace();
throw new IllegalArgumentException(ErrorMessage.FAILED_TO_SEND_EMAIL);
}
return ePw; // 메일로 보냈던 인증 코드를 서버로 리턴
}
기존에 createKey() 메서드를 이용해 인증 코드를 생성하던 것을 sendSimpleMessage 메서드 안으로 이동하고, ePw라는 전역 변수를 제거하여 각 요청마다 새로운 인증코드를 생성하게 하였다.
'코딩과 매일매일♥ > Game_Crew' 카테고리의 다른 글
[Game_Crew] 트러블슈팅 : S3 + 이미지 리사이징 적용하기 (0) | 2023.11.11 |
---|---|
[Game_Crew] WebSocket으로 1대1 채팅기능 구현하기(1) - 적용x (0) | 2023.11.01 |
[Game_Crew] 트러블슈팅 : 이메일 인증 완성 (0) | 2023.10.27 |
[Game_Crew] 유저 평점 기능 (0) | 2023.10.27 |
231026 - [Game_Crew]트러블슈팅 : CORS 설정하기 (0) | 2023.10.26 |