비밀번호 찾기 로직 수정, 디자인 적용
This commit is contained in:
+9
@@ -113,11 +113,20 @@ public class AccountRecoveryController {
|
||||
|
||||
// 세션에서 인증 여부 확인
|
||||
Boolean isVerified = (Boolean) session.getAttribute("isVerified");
|
||||
String sessionMobileNumber = (String) session.getAttribute("mobileNumber");
|
||||
|
||||
if (isVerified == null || !isVerified) {
|
||||
setModelForError(redirectAttributes, "resetPassword", null, "휴대폰 번호 인증을 먼저 진행해주세요.", null, passwordReset);
|
||||
return "redirect:/account_recovery?tab=resetPassword";
|
||||
}
|
||||
|
||||
// 인증된 전화번호와 입력된 전화번호 일치 여부 확인
|
||||
if (passwordReset.getMobileNumber() == null ||
|
||||
!passwordReset.getMobileNumber().replace("-", "").equals(sessionMobileNumber)) {
|
||||
setModelForError(redirectAttributes, "resetPassword", null, "인증된 휴대폰 번호와 입력한 번호가 일치하지 않습니다.", null, passwordReset);
|
||||
return "redirect:/account_recovery?tab=resetPassword";
|
||||
}
|
||||
|
||||
try {
|
||||
// 사용자 정보 확인
|
||||
portalUserAuthService.resetPassword(
|
||||
|
||||
@@ -101,11 +101,12 @@ public class PortalUserAuthService implements UserDetailsService {
|
||||
}
|
||||
|
||||
public void resetPassword(String loginId, String userName, String mobileNumber) {
|
||||
// 전화번호에서 - 제거하여 정규화
|
||||
String normalizedMobileNumber = mobileNumber != null ? mobileNumber.replace("-", "") : null;
|
||||
|
||||
PortalUser portalUser = portalUserRepository.findByLoginIdAndUserNameAndMobileNumber(loginId, userName, mobileNumber)
|
||||
PortalUser portalUser = portalUserRepository.findByLoginIdAndUserNameAndMobileNumber(loginId, userName, normalizedMobileNumber)
|
||||
.orElseThrow(() -> new UserNotFoundException("일치하는 사용자 정보를 찾을 수 없습니다."));
|
||||
|
||||
// String tempPassword = EncryptionUtil.generateNewPasswordForKjbank(loginId);
|
||||
String tempPassword = EncryptionUtil.generateNewPassword();
|
||||
portalUser.setPasswordHash(passwordEncoder.encode(tempPassword));
|
||||
if ("Y".equalsIgnoreCase(portalUser.getAccountLockYn())) {
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_base_layout}">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_title_layout}">
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>비밀번호 초기화</h1>
|
||||
</div>
|
||||
</section>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Logo -->
|
||||
<div class="account-recovery-logo">
|
||||
<img th:src="@{/img/logo/logo_box.png}" alt="광주은행">
|
||||
</div>
|
||||
|
||||
<!-- Header Title -->
|
||||
<h2 class="account-recovery-title">비밀번호 초기화</h2>
|
||||
|
||||
<!-- Tab Navigation -->
|
||||
<div class="account-recovery-tabs">
|
||||
<a th:href="@{/account_recovery(tab='findId')}" class="tab-link">아이디 찾기</a>
|
||||
<a th:href="@{/account_recovery(tab='findId')}" class="tab-link">아이디찾기</a>
|
||||
<a href="#" class="tab-link active">비밀번호 초기화</a>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +28,7 @@
|
||||
|
||||
<!-- Name Field -->
|
||||
<div class="form-group">
|
||||
<label for="userName" class="form-label">성명</label>
|
||||
<label for="userName" class="form-label">성명<span class="required">*</span></label>
|
||||
<input type="text"
|
||||
id="userName"
|
||||
name="userName"
|
||||
@@ -42,7 +40,7 @@
|
||||
|
||||
<!-- Email ID Field -->
|
||||
<div class="form-group">
|
||||
<label for="loginId" class="form-label">이메일 아이디</label>
|
||||
<label for="loginId" class="form-label">이메일 아이디<span class="required">*</span></label>
|
||||
<input type="email"
|
||||
id="loginId"
|
||||
name="loginId"
|
||||
@@ -54,7 +52,7 @@
|
||||
|
||||
<!-- Phone Number Fields -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">휴대폰 번호</label>
|
||||
<label class="form-label">휴대폰 번호<span class="required">*</span></label>
|
||||
<div class="phone-input-group">
|
||||
<select id="phonePrefix" class="form-select phone-prefix" required>
|
||||
<option value="">선택</option>
|
||||
@@ -64,37 +62,35 @@
|
||||
<option value="017">017</option>
|
||||
<option value="018">018</option>
|
||||
</select>
|
||||
<span class="phone-separator">-</span>
|
||||
<span class="phone-separator"></span>
|
||||
<input type="tel"
|
||||
id="phoneMiddle"
|
||||
name="phoneMiddle"
|
||||
maxlength="4"
|
||||
class="form-input phone-middle"
|
||||
placeholder="0000"
|
||||
placeholder="1234"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
required>
|
||||
<span class="phone-separator">-</span>
|
||||
<span class="phone-separator"></span>
|
||||
<input type="tel"
|
||||
id="phoneLast"
|
||||
name="phoneLast"
|
||||
maxlength="4"
|
||||
class="form-input phone-last"
|
||||
placeholder="0000"
|
||||
placeholder="1234"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
required>
|
||||
<button type="button" class="auth-request-button" id="requestAuthButton">
|
||||
인증번호 받기
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Number Request Button -->
|
||||
<button type="button" class="auth-request-button" id="requestAuthButton">
|
||||
인증번호 받기
|
||||
</button>
|
||||
|
||||
<!-- Auth Number Input -->
|
||||
<div class="form-group auth-number-group" id="authNumberGroup" style="display: none;">
|
||||
<label for="authNumber" class="form-label">인증번호 입력</label>
|
||||
<label for="authNumber" class="form-label">인증번호 입력<span class="required">*</span></label>
|
||||
<div class="auth-input-group">
|
||||
<input type="text"
|
||||
id="authNumber"
|
||||
@@ -107,20 +103,18 @@
|
||||
required>
|
||||
<span class="auth-timer" id="authTimer">03:00</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Number Verify Button -->
|
||||
<button type="button" class="auth-verify-button" id="verifyAuthButton" style="display: none;">
|
||||
인증번호 확인
|
||||
</button>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="cancel-button" id="cancelButton">취소</button>
|
||||
<button type="submit" class="submit-button" id="submitButton">비밀번호 초기화</button>
|
||||
<button type="button" class="auth-verify-button" id="verifyAuthButton">
|
||||
인증번호 확인
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="cancel-button" id="cancelButton">취소</button>
|
||||
<button type="submit" class="submit-button" id="submitButton" form="accountForm">비밀번호 초기화</button>
|
||||
</div>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div class="loading-overlay" id="loadingOverlay">
|
||||
<div class="spinner"></div>
|
||||
@@ -135,32 +129,20 @@
|
||||
$(document).ready(function() {
|
||||
const errorMsg = [[${error}]];
|
||||
if (errorMsg) {
|
||||
showAlert(errorMsg, 'error');
|
||||
customPopups.showAlert(errorMsg, 'error');
|
||||
}
|
||||
|
||||
const successMsg = [[${success}]];
|
||||
if (successMsg) {
|
||||
customPopups.showAlert(successMsg, 'success');
|
||||
}
|
||||
|
||||
const paramError = new URL(window.location.href).searchParams.get('error');
|
||||
if (paramError) {
|
||||
showAlert(decodeURIComponent(paramError), 'error');
|
||||
customPopups.showAlert(decodeURIComponent(paramError), 'error');
|
||||
}
|
||||
});
|
||||
|
||||
// Alert 표시 함수
|
||||
function showAlert(message, type = 'info') {
|
||||
const alertContainer = $('#alertContainer');
|
||||
const alertClass = type === 'error' ? 'alert-error' : type === 'success' ? 'alert-success' : 'alert-info';
|
||||
const iconClass = type === 'error' ? 'fa-exclamation-circle' : type === 'success' ? 'fa-check-circle' : 'fa-info-circle';
|
||||
|
||||
const alertHtml = `
|
||||
<div class="account-alert ${alertClass}">
|
||||
<i class="fas ${iconClass}"></i>
|
||||
<span>${message}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
alertContainer.html(alertHtml);
|
||||
setTimeout(() => alertContainer.empty(), 5000);
|
||||
}
|
||||
|
||||
// 휴대폰 번호 결합 함수
|
||||
function combineMobileNumber() {
|
||||
const prefix = $('#phonePrefix').val();
|
||||
@@ -188,7 +170,7 @@
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
$('#authTimer').text('시간 초과').css('color', '#FF6B6B');
|
||||
showAlert('입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.', 'error');
|
||||
customPopups.showAlert('입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.', 'error');
|
||||
|
||||
// 필드 활성화
|
||||
$('#phonePrefix, #phoneMiddle, #phoneLast').prop('disabled', false);
|
||||
@@ -210,25 +192,25 @@
|
||||
$('#requestAuthButton').on('click', function() {
|
||||
const userName = $('#userName').val().trim();
|
||||
if (!userName) {
|
||||
showAlert('성명을 입력해주세요.', 'error');
|
||||
customPopups.showAlert('성명을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginId = $('#loginId').val().trim();
|
||||
if (!loginId) {
|
||||
showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
customPopups.showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(loginId)) {
|
||||
showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
customPopups.showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const mobileNumber = combineMobileNumber();
|
||||
if (!mobileNumber) {
|
||||
showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -246,7 +228,7 @@
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
|
||||
if (response.valid) {
|
||||
showAlert(response.message || '인증번호가 발송되었습니다.', 'success');
|
||||
customPopups.showAlert(response.message || '인증번호가 발송되었습니다.', 'success');
|
||||
|
||||
// 휴대폰 번호 필드 비활성화
|
||||
$('#phonePrefix, #phoneMiddle, #phoneLast').prop('disabled', true);
|
||||
@@ -259,12 +241,12 @@
|
||||
isAuthNumberRequested = true;
|
||||
startAuthTimer();
|
||||
} else {
|
||||
showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error');
|
||||
customPopups.showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -272,14 +254,14 @@
|
||||
// 인증번호 확인 버튼
|
||||
$('#verifyAuthButton').on('click', function() {
|
||||
if (!isAuthNumberRequested) {
|
||||
showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error');
|
||||
customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const authNumber = $('#authNumber').val().trim();
|
||||
|
||||
if (authNumber.length !== 6) {
|
||||
showAlert('인증번호 6자리를 입력해주세요.', 'error');
|
||||
customPopups.showAlert('인증번호 6자리를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -298,7 +280,7 @@
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
|
||||
if (response.valid) {
|
||||
showAlert(response.message || '인증이 완료되었습니다.', 'success');
|
||||
customPopups.showAlert(response.message || '인증이 완료되었습니다.', 'success');
|
||||
|
||||
// 인증번호 입력 필드 비활성화
|
||||
$('#authNumber').prop('disabled', true);
|
||||
@@ -309,12 +291,12 @@
|
||||
|
||||
isAuthVerified = true;
|
||||
} else {
|
||||
showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error');
|
||||
customPopups.showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -325,35 +307,35 @@
|
||||
|
||||
const userName = $('#userName').val().trim();
|
||||
if (!userName) {
|
||||
showAlert('성명을 입력해주세요.', 'error');
|
||||
customPopups.showAlert('성명을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const loginId = $('#loginId').val().trim();
|
||||
if (!loginId) {
|
||||
showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
customPopups.showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(loginId)) {
|
||||
showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
customPopups.showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const mobileNumber = combineMobileNumber();
|
||||
if (!mobileNumber) {
|
||||
showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthNumberRequested) {
|
||||
showAlert('휴대폰 인증을 먼저 진행해주세요.', 'error');
|
||||
customPopups.showAlert('휴대폰 인증을 먼저 진행해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthVerified) {
|
||||
showAlert('휴대폰 인증을 완료해주세요.', 'error');
|
||||
customPopups.showAlert('휴대폰 인증을 완료해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
|
||||
<body>
|
||||
<section layout:fragment="contentFragment" class="content">
|
||||
<div class="content_wrap">
|
||||
<!-- 타이틀 -->
|
||||
<div class="sub_title2">
|
||||
<h2 class="title add5">비밀번호 초기화</h2>
|
||||
</div>
|
||||
|
||||
<div class="inner i_cs10 h_inner2">
|
||||
<!-- 탭 메뉴 -->
|
||||
<div class="tab-wrap">
|
||||
<div class="tabs">
|
||||
<ul class="tab_nav tabm">
|
||||
<li><a href="#tab1">아이디 찾기</a></li>
|
||||
<li class="active"><a href="#tab2">비밀번호 초기화</a></li>
|
||||
</ul>
|
||||
<div class="tab active" id="tab2">
|
||||
<div class="form_type">
|
||||
<div class="result_view">
|
||||
<p class="title" th:tex="${successMessage}"></p>
|
||||
</div>
|
||||
<div class="btn_application btn_top3">
|
||||
<a href="/login" class="common_btn_type_1"><span>로그인</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
</th:block>
|
||||
</html>
|
||||
Reference in New Issue
Block a user