From 3ad3bd087e8100e3ec459cb86649472c2c13da36 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 1 Oct 2025 20:32:44 +0900 Subject: [PATCH] =?UTF-8?q?=ED=9C=B4=EB=8C=80=ED=8F=B0=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=A4=91=EB=B3=B5=20=EA=B0=80=EC=9E=85=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/service/AuthNumberServiceImpl.java | 6 ++ .../apps/user/controller/AuthController.java | 34 +++++++++- .../apps/user/facade/AuthFacadeImpl.java | 10 ++- .../user/facade/UserRegisterFacadeImpl.java | 67 ++++++++++--------- 4 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/apps/auth/service/AuthNumberServiceImpl.java b/src/main/java/com/eactive/apim/portal/apps/auth/service/AuthNumberServiceImpl.java index e32a34f..3e9bbd2 100644 --- a/src/main/java/com/eactive/apim/portal/apps/auth/service/AuthNumberServiceImpl.java +++ b/src/main/java/com/eactive/apim/portal/apps/auth/service/AuthNumberServiceImpl.java @@ -37,9 +37,15 @@ public class AuthNumberServiceImpl implements AuthNumberService { this.messageSender = messageSender; } + /** + * 이메일 인증도 가능하도록 개선 + * @param recipientKey + * @param msgType + */ @Override @Transactional(noRollbackFor = AuthNumberException.class) public void sendRequestAuthNumber(String recipientKey, String msgType) { + // TODO: 이메일 인증도 가능하도록 개선 logger.info("Sending auth number to: {} via {}", recipientKey, msgType); validateResendTime(recipientKey); diff --git a/src/main/java/com/eactive/apim/portal/apps/user/controller/AuthController.java b/src/main/java/com/eactive/apim/portal/apps/user/controller/AuthController.java index c9ef805..b933c9c 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/controller/AuthController.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/controller/AuthController.java @@ -2,6 +2,7 @@ package com.eactive.apim.portal.apps.user.controller; import com.eactive.apim.portal.apps.user.dto.ValidationResponse; import com.eactive.apim.portal.apps.user.facade.AuthFacade; +import com.eactive.apim.portal.apps.user.validator.EmailValidator; import com.eactive.apim.portal.common.validator.CellPhoneValidator; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -20,12 +21,16 @@ public class AuthController { private final AuthFacade authFacade; private final CellPhoneValidator cellPhoneValidator; + private final EmailValidator emailValidator; - public AuthController(AuthFacade authFacade, CellPhoneValidator cellPhoneValidator) { + + public AuthController(AuthFacade authFacade, CellPhoneValidator cellPhoneValidator, EmailValidator emailValidator) { this.authFacade = authFacade; this.cellPhoneValidator = cellPhoneValidator; + this.emailValidator = emailValidator; } + @PostMapping("/request_auth_number") public ValidationResponse requestAuthNumber( @RequestParam(required = false) String mobileNumber, @@ -89,6 +94,33 @@ public class AuthController { return response; } + + @PostMapping("/request-otp-email") + public ValidationResponse requestOtpForEmail( + @RequestParam(required = false) String email, + HttpSession session) { + + // TODO: 이메일 주소 인증 기능 개선 + + ValidationResponse response = new ValidationResponse(); + email = email.trim(); + + if (!emailValidator.isValidEmail(email)) { + response.setValid(false); + response.setMessage("유효하지 않은 이메일 형식입니다."); + return response; + } + + response = authFacade.requestAuth(email, "EMAIL"); + + if (response.isValid()) { +// session.setAttribute("mobileNumber", sanitizedMobile); + } + + return response; + } + + private void clearAuthSessionData(HttpSession session) { session.removeAttribute("mobileNumber"); session.removeAttribute("isVerified"); diff --git a/src/main/java/com/eactive/apim/portal/apps/user/facade/AuthFacadeImpl.java b/src/main/java/com/eactive/apim/portal/apps/user/facade/AuthFacadeImpl.java index 06a5e16..0b84483 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/facade/AuthFacadeImpl.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/facade/AuthFacadeImpl.java @@ -15,6 +15,14 @@ public class AuthFacadeImpl implements AuthFacade { private final AuthNumberService authNumberService; private static final Logger log = LoggerFactory.getLogger(AuthFacadeImpl.class); + + /** + * 인증 요청 + * 25.10.01 - 이메일 인증도 가능하도록 개선 + * @param recipientKey + * @param msgType "SMS", "EMAIL" (대소문자 구분 안함) + * @return + */ @Override public ValidationResponse requestAuth(String recipientKey, String msgType) { ValidationResponse response = new ValidationResponse(); @@ -26,7 +34,7 @@ public class AuthFacadeImpl implements AuthFacade { return response; } - if (!"SMS".equalsIgnoreCase(msgType)) { + if (!"SMS".equalsIgnoreCase(msgType) && !"EMAIL".equalsIgnoreCase(msgType)) { response.setValid(false); response.setMessage("유효하지 않은 인증 방식입니다."); return response; diff --git a/src/main/java/com/eactive/apim/portal/apps/user/facade/UserRegisterFacadeImpl.java b/src/main/java/com/eactive/apim/portal/apps/user/facade/UserRegisterFacadeImpl.java index 62a25e2..1af158c 100644 --- a/src/main/java/com/eactive/apim/portal/apps/user/facade/UserRegisterFacadeImpl.java +++ b/src/main/java/com/eactive/apim/portal/apps/user/facade/UserRegisterFacadeImpl.java @@ -2,6 +2,7 @@ package com.eactive.apim.portal.apps.user.facade; import com.eactive.apim.portal.agreements.entity.AgreementType; import com.eactive.apim.portal.apps.agreements.service.AgreementsFacade; +import com.eactive.apim.portal.apps.auth.service.AuthNumberGenerator; import com.eactive.apim.portal.apps.user.dto.PortalUserRegistrationDTO; import com.eactive.apim.portal.apps.user.dto.UserAgreementDTO; import com.eactive.apim.portal.apps.user.dto.ValidationResponse; @@ -10,7 +11,6 @@ import com.eactive.apim.portal.apps.user.service.PortalUserService; import com.eactive.apim.portal.apps.user.service.UserRegistrationValidationService; import com.eactive.apim.portal.apps.user.validator.AgreementValidator; import com.eactive.apim.portal.apps.user.validator.PasswordValidator; -import com.eactive.apim.portal.common.exception.SystemException; import com.eactive.apim.portal.common.util.EncryptionUtil; import com.eactive.apim.portal.invitation.entity.UserInvitation; import com.eactive.apim.portal.invitation.entity.UserInvitationEnums; @@ -20,19 +20,7 @@ import com.eactive.apim.portal.portaluser.event.UserEmailActivationEvent; import com.eactive.apim.portal.portaluser.repository.PortalUserRepository; import com.eactive.apim.portal.template.service.MessageHandlerService; import com.eactive.apim.portal.template.service.MessageRecipient; -import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.Optional; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; -import org.apache.xerces.impl.dv.util.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.crypto.password.PasswordEncoder; @@ -41,6 +29,11 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; +import javax.servlet.http.HttpSession; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Optional; + @Service @RequiredArgsConstructor public class UserRegisterFacadeImpl implements UserRegisterFacade { @@ -58,6 +51,8 @@ public class UserRegisterFacadeImpl implements UserRegisterFacade { private final AgreementValidator agreementValidator; private final MessageHandlerService messageHandlerService; private final EncryptionUtil encryptionUtil; + private final AuthNumberGenerator authNumberGenerator; + @Override public ValidationResponse handleCheckId(String loginId, String registrationType) { @@ -110,7 +105,7 @@ public class UserRegisterFacadeImpl implements UserRegisterFacade { ValidationResponse response = new ValidationResponse(); Optional user = portalUserRepository.findPortalUserByEmailAddr(loginId); - if (user != null && passwordEncoder.matches(confirmPassword, user.get().getPasswordHash())) { + if (user.isPresent() && passwordEncoder.matches(confirmPassword, user.get().getPasswordHash())) { response.setValid(true); response.setMessage("비밀번호가 확인되었습니다."); } else { @@ -137,20 +132,22 @@ public class UserRegisterFacadeImpl implements UserRegisterFacade { return new ValidationResponse(false,"입력값을 확인해 주세요."); } - PortalUser existingUser = portalUserRepository.findByUserNameAndMobileNumber(registrationDTO.getUserName(), registrationDTO.getMobileNumber()); + // 25.10.01 - 휴대폰 번호 중복이여도 가입 가능 +// PortalUser existingUser = portalUserRepository.findByUserNameAndMobileNumber(registrationDTO.getUserName(), registrationDTO.getMobileNumber()); +// +// if(existingUser != null) { +// return new ValidationResponse(false, "가입된 계정이 이미 존재합니다."); +// } - if(existingUser != null) { - return new ValidationResponse(false, "가입된 계정이 이미 존재합니다."); + // 3. 사용자 등록 ("personal" 등록 유형으로 가정) + PortalUser newUser = portalUserService.registerActiveUser(registrationDTO, "personal"); + if (newUser == null) { + return new ValidationResponse(false,"사용자 등록에 실패했습니다."); } - // 3. 사용자 등록 ("personal" 등록 유형으로 가정) - PortalUser newUser = portalUserService.registerActiveUser(registrationDTO, "personal"); - if (newUser == null) { - return new ValidationResponse(false,"사용자 등록에 실패했습니다."); - } - agreementsFacade.saveUserAgreements(newUser.getId(), AgreementType.PRIVACY_COLLECT_IND); - sendEmailActivation(newUser); - return new ValidationResponse(true,"회원가입이 완료되었습니다."); + agreementsFacade.saveUserAgreements(newUser.getId(), AgreementType.PRIVACY_COLLECT_IND); + sendEmailActivation(newUser); + return new ValidationResponse(true,"회원가입이 완료되었습니다."); } @Override @@ -217,16 +214,20 @@ public class UserRegisterFacadeImpl implements UserRegisterFacade { recipient.setUserId(registeredUser.getEmailAddr()); recipient.setPhone(registeredUser.getMobileNumber()); + // 25.10.01 - 이메일 링크 방식으로 접근 불가이기에 SMS 인증방식과 동일하게 대체 HashMap params = new HashMap<>(); - String tokenValue = registeredUser.getCreatedDate().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + ":" + registeredUser.getId(); - try { - String encToken = encryptionUtil.encrypt(tokenValue); - params.put("token", Base64.encode(encToken.getBytes(StandardCharsets.UTF_8))); - messageHandlerService.publishEvent(UserEmailActivationEvent.KEY, recipient, params); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { - throw new SystemException("암호화 모듈 오류"); - } + String tokenValue = String.valueOf(authNumberGenerator.generateAuthNumber()); + // String tokenValue = registeredUser.getCreatedDate().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + ":" + registeredUser.getId(); + params.put("token", tokenValue); + messageHandlerService.publishEvent(UserEmailActivationEvent.KEY, recipient, params); +// try { +// String encToken = encryptionUtil.encrypt(tokenValue); +// params.put("token", Base64.encode(encToken.getBytes(StandardCharsets.UTF_8))); +// messageHandlerService.publishEvent(UserEmailActivationEvent.KEY, recipient, params); +// } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { +// throw new SystemException("암호화 모듈 오류"); +// } } @Override