이메일 인증 클라이언트 방식 → 서버 방식으로 수정
원래 아이디/비밀번호 찾기 기능에서 이메일 인증을 할 때 JS에서 생성한 인증번호와 사용자가 입력한 인증번호를 비교했는데 이 방식은 클라이언트 방식으로, 보안에 취약할 수 있다고 해서 이번에 리팩토링 겸 서버 방식으로 바꾸었다.
원래 인증번호를 JS에서 비교하는 클라이언트 방식이었지만, 개발자 도구(F12)를 통해 코드나 값이 노출될 위험이 있어 보안상 취약했다. 이를 해결하기 위해, 인증번호를 서버 세션에 저장하고, 서버에서 직접 비교하는 서버 방식으로 개선했다. (애초에 사실 세션에도 저장하고 있었는데 잘 몰라서 세션에도 저장을 해두었다) 이 방식은 인증번호가 외부에 노출되지 않기 때문에 더 안전하다.
1. 사용자가 입력한 정보를 받아 DB에서 정보를 조회한다
2. 만약 존재하는 회원이라면 6자리 인증번호를 생성하여 세션에 저장하고
3. 사용자 이메일로 인증번호를 전송한다.
4. 사용자가 인증번호를 받고 버튼을 누르면 프론트에서 서버로 그 값을 전달하고(AJAX)
5. 서버에서 인증번호를 비교한다
6. 세션에 저장된 인증번호를 가져와서 입력값과 비교하고 일치 여부를 판단한 후
7. 일치하면 세션에서 인증번호를 삭제한다
8. 인증 성공 시 해당 사용자 ID를 세션에 저장한 후 비밀번호 재설정으로 넘어간다.
// 이메일 인증번호 비교 로직
@PostMapping("/member/checkEmailCode")
@ResponseBody
public Map<String, Object> checkEmailCode(@RequestParam("code") String inputCode, HttpSession session) {
Map<String, Object> result = new HashMap<>(); // Map 객체 선언
// 세션에 저장된 인증번호 가져옴
String storedCode = (String) session.getAttribute("verificationCode");
// 만약 인증번호가 존재하고 사용자가 입력한 인증번호와 같다면
if (storedCode != null && storedCode.equals(inputCode)) {
// 인증 성공 응답
result.put("valid", true);
// 인증 완료 후 세션에서 인증번호 제거
session.removeAttribute("verificationCode");
} else { // 인증 실패 시
result.put("valid", false); // 인증 실패 응답
}
return result; // 결과는 JSON으로 반환
}
}
이메일 인증 컨트롤러 아래 이메일 인증번호를 비교하는 로직을 하나 추가했다.
이게 없으면 서버에서 비교를 할 수 없다.
// 이메일 인증 (서버 비교 방식)
if (authMethod === "email") {
// 입력된 인증번호가 없다면
if (!inputCode) {
printSweetAlert("warning", "인증번호를 입력해주세요."); // 경고 안내 출력
return;
}
// 서버 측에 인증번호 비교 요청
$.ajax({
type: "POST",
url: "/member/checkEmailCode", // 인증번호 비교 컨트롤러
data: { code: inputCode }, // 사용자가 입력한 인증번호
dataType: "json", // JSON으로 받음
// 요청 성공
success: (res) => {
if (res.valid) { // 인증 성공
printSweetAlert("success", "성공적으로 인증됐습니다."); //메시지 출력
clearInterval(timer); // 타이머 종료
timerElement.addClass("hidden"); // 타이머 숨김
sendingconfirm.addClass("hidden");
inputConfirm.val("").prop("readonly", true); // 입력창 변경
sendingConfirmNumber = 0; // 초기화
$('button.submit-btn').prop('disabled', false); // 초기화
confirmBtn.text("재인증"); // 버튼 문구 변경
} else { // 인증 실패
printSweetAlert("warning", "옳지 않은 인증번호입니다."); //메시지 출력
}
},
// 서버 오류 시
error: () => {
printSweetAlert("error", "서버 오류가 발생했습니다."); // 에러 메시지 출력
}
});
return;
}
그리고 findAccount.js에서 해당 부분을 수정해줬다.
해당 js에서 사용자 입력값을 컨트롤러에 보내주고, 컨트롤러가 인증번호 비교 후 JSON으로 값을 반환해주면 해당 값에 따라 UI를 다르게 출력하도록 한다.