이메일 형식 및 비밀번호 조건 검증 추가

This commit is contained in:
choibk 2025-12-04 15:41:44 +09:00
parent d88faa6c6b
commit d4d655b870
4 changed files with 218 additions and 90 deletions

View File

@ -20,6 +20,11 @@ class Member {
return $stmt->rowCount() ? true : false; return $stmt->rowCount() ? true : false;
} }
// 이메일 형식 체크
public function email_format_check($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
public function email_exists($email) { public function email_exists($email) {
$sql = "SELECT * FROM member WHERE email=:email"; $sql = "SELECT * FROM member WHERE email=:email";
$stmt = $this->conn->prepare($sql); $stmt = $this->conn->prepare($sql);

View File

@ -78,71 +78,91 @@ document.addEventListener("DOMContentLoaded", () => {
} else if (data.result == 'empty_id') { } else if (data.result == 'empty_id') {
alert('이메일이 입력되지 않았습니다.') alert('이메일이 입력되지 않았습니다.')
f_email.focus() f_email.focus()
} else if(data.result == 'email_format_wrong') {
alert('이메일 형식이 맞지 않습니다.')
f_email.focus()
} }
} }
} }
}) })
// 비밀번호 규칙 검사용 정규식
// - 최소 8자
// - 소문자 1개 이상
// - 대문자 1개 이상
// - 숫자 1개 이상
// - 특수문자 1개 이상
const passwordRule = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/;
// 가입 버튼 클릭 시 비밀번호 일치 체크 // 가입 버튼 클릭 시 비밀번호 일치 체크
const btn_submit = document.querySelector("#btn_submit") const btn_submit = document.querySelector("#btn_submit");
btn_submit.addEventListener("click", () => { btn_submit.addEventListener("click", () => {
const f = document.input_form const f = document.input_form;
if (f.id.value == '') {
alert('아이디를 입력해 주세요.') if (f.id.value.trim() === '') {
f.id.focus() alert('아이디를 입력해 주세요.');
return false f.id.focus();
return false;
} }
// 아이디 중복 체크 여부 // 아이디 중복 체크 여부
if (f.id_chk.value == 0) { if (f.id_chk.value === "0") {
alert('아이디 중복확인이 필요합니다.') alert('아이디 중복확인이 필요합니다.');
return false return false;
} }
// 비밀번호 입력 여부 // 비밀번호 입력 여부
if (f.password.value == '') { if (f.password.value === '') {
alert('비밀번호를 입력하세요.') alert('비밀번호를 입력하세요.');
f.password.focus() f.password.focus();
return false return false;
} }
if (f.password2.value == '') { if (f.password2.value === '') {
alert('비밀번호 확인이 필요합니다.') alert('비밀번호 확인이 필요합니다.');
f.password2.focus() f.password2.focus();
return false return false;
}
// ★ 비밀번호 규칙 검사 추가 (여기)
if (!passwordRule.test(f.password.value)) {
alert('비밀번호는 8자 이상이며, 대문자/소문자/숫자/특수문자를 모두 포함해야 합니다.');
f.password.focus();
return false;
} }
// 비밀번호 일치 여부 // 비밀번호 일치 여부
if (f.password.value != f.password2.value) { if (f.password.value !== f.password2.value) {
alert('비밀번호가 일치하지 않습니다.') alert('비밀번호가 일치하지 않습니다.');
//f.password.value = '' // f.password.value = '';
f.password2.value = '' f.password2.value = '';
f.password2.focus() f.password2.focus();
return false return false;
} }
// 이름 등록 여부 // 이름 등록 여부
if (f.name.value == '') { if (f.name.value.trim() === '') {
alert('이름을 입력해 주세요.') alert('이름을 입력해 주세요.');
f.name.focus() f.name.focus();
return false return false;
} }
// 이메일 등록 여부 // 이메일 등록 여부
if (f.email.value == '') { if (f.email.value.trim() === '') {
alert('이메일을 입력해 주세요') alert('이메일을 입력해 주세요');
f.email.focus() f.email.focus();
return false return false;
} }
// 이메일 중복 체크 여부 // 이메일 중복 체크 여부
if(f.email_chk.value == 0) { if (f.email_chk.value === "0") {
alert('이메일 중복확인이 필요합니다.') alert('이메일 중복확인이 필요합니다.');
return false return false;
} }
f.submit() f.submit();
});
})
// 우편번호 찾기 // 우편번호 찾기

View File

@ -29,7 +29,7 @@ include 'header.php';
<div class="d-flex gap-2 align-items-end"> <div class="d-flex gap-2 align-items-end">
<div class="flex-grow-1"> <div class="flex-grow-1">
<label for="f_id">아이디</label> <label for="f_id">아이디</label>
<input typ="text" name="id" class="form-control" id="f_id" placeholder="아이디를 입력하세요"> <input type="text" name="id" class="form-control" id="f_id" placeholder="아이디를 입력하세요">
</div> </div>
<button type="button" class="btn btn-secondary" id="btn_id_check"> 아이디 중복확인 </button> <button type="button" class="btn btn-secondary" id="btn_id_check"> 아이디 중복확인 </button>
</div> </div>
@ -48,14 +48,14 @@ include 'header.php';
<div class="d-flex mt-3 gap-2 align-items-end"> <div class="d-flex mt-3 gap-2 align-items-end">
<div class="w-50"> <div class="w-50">
<label for="f_name">이름</label> <label for="f_name">이름</label>
<input typ="text" name="name" class="form-control" id="f_name" placeholder="이름을 입력하세요"> <input type="text" name="name" class="form-control" id="f_name" placeholder="이름을 입력하세요">
</div> </div>
</div> </div>
<div class="d-flex mt-3 gap-2 align-items-end"> <div class="d-flex mt-3 gap-2 align-items-end">
<div class="flex-grow-1"> <div class="flex-grow-1">
<label for="f_email">이메일</label> <label for="f_email">이메일</label>
<input typ="text" name="email" class="form-control" id="f_email" placeholder="이메일을 입력하세요"> <input type="text" name="email" class="form-control" id="f_email" placeholder="이메일을 입력하세요">
</div> </div>
<button type="button" id="btn_email_check" class="btn btn-secondary"> 이메일 중복확인 </button> <button type="button" id="btn_email_check" class="btn btn-secondary"> 이메일 중복확인 </button>
</div> </div>
@ -71,11 +71,11 @@ include 'header.php';
<div class="d-flex mt-3 gap-2 justify-content-between"> <div class="d-flex mt-3 gap-2 justify-content-between">
<div class="w-50"> <div class="w-50">
<label for="f_addr1" class="form-label">주소</label> <label for="f_addr1" class="form-label">주소</label>
<input typ="text" name="addr1" class="form-control" id="f_addr1" placeholder="주소를 입력하세요"> <input type="text" name="addr1" class="form-control" id="f_addr1" placeholder="주소를 입력하세요">
</div> </div>
<div class="w-50"> <div class="w-50">
<label for="f_addr2" class="form-label">상세주소</label> <label for="f_addr2" class="form-label">상세주소</label>
<input typ="text" name="addr2" class="form-control" id="f_addr2" placeholder="상세주소를 입력하세요"> <input type="text" name="addr2" class="form-control" id="f_addr2" placeholder="상세주소를 입력하세요">
</div> </div>
</div> </div>

View File

@ -1,57 +1,144 @@
<?php <?php
// 맨 첫 줄들에 추가 // 개발 단계: 에러 표시
ini_set('display_errors', 1); ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
// 세션 시작
session_start();
include '../config/dbconfig.php'; // 상대경로 include '../config/dbconfig.php'; // 상대경로
include '../config/member.php'; include '../config/member.php';
$mem = new Member($db); $mem = new Member($db);
$id = (isset($_POST['id']) && $_POST['id'] != '') ? $_POST['id'] : ''; // ===== 공통 입력값 수집 =====
$password = (isset($_POST['password']) && $_POST['password'] != '') ? $_POST['password'] : ''; $id = isset($_POST['id']) ? trim($_POST['id']) : '';
$email = (isset($_POST['email']) && $_POST['email'] != '') ? $_POST['email'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : '';
$name = (isset($_POST['name']) && $_POST['name'] != '') ? $_POST['name'] : ''; $email = isset($_POST['email']) ? trim($_POST['email']) : '';
$zipcode = (isset($_POST['zipcode']) && $_POST['zipcode'] != '') ? $_POST['zipcode'] : ''; $name = isset($_POST['name']) ? trim($_POST['name']) : '';
$addr1 = (isset($_POST['addr1']) && $_POST['addr1'] != '') ? $_POST['addr1'] : ''; $zipcode = isset($_POST['zipcode']) ? trim($_POST['zipcode']) : '';
$addr2 = (isset($_POST['addr2']) && $_POST['addr2'] != '') ? $_POST['addr2'] : ''; $addr1 = isset($_POST['addr1']) ? trim($_POST['addr1']) : '';
$mode = (isset($_POST['mode']) && $_POST['mode'] != '') ? $_POST['mode'] : ''; $addr2 = isset($_POST['addr2']) ? trim($_POST['addr2']) : '';
$mode = isset($_POST['mode']) ? trim($_POST['mode']) : '';
// 아이디 중복 체크 // ===== 비밀번호 규칙 서버 검증 함수 =====
if ($mode == 'id_chk') { // 최소 8자, 소문자/대문자/숫자/특수문자 각 1개 이상
if ($id == '') { function password_check($pwd)
{
return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/', $pwd);
}
// ===== redirect + session 헬퍼 =====
function redirect_with_error($message)
{
// 이전 입력값 저장
$_SESSION['join_old'] = $_POST;
$_SESSION['join_error'] = $message;
// 폼 페이지로 리다이렉트 (member_input.php)
header('Location: ../member_input.php');
exit;
}
// ======================
// 1. 아이디 중복 체크 (AJAX)
// ======================
if ($mode === 'id_chk') {
if ($id === '') {
die(json_encode(['result' => 'empty_id'])); die(json_encode(['result' => 'empty_id']));
} }
if ($mem->id_exists($id)) { if ($mem->id_exists($id)) {
die(json_encode(['result' => 'fail'])); die(json_encode(['result' => 'fail']));
} else { } else {
die(json_encode(['result' => 'success'])); die(json_encode(['result' => 'success']));
} }
// 이메일 중복 체크
} else if ($mode == 'email_chk') { // ======================
if ($email == '') { // 2. 이메일 중복 체크 (AJAX)
// ======================
} else if ($mode === 'email_chk') {
if ($email === '') {
die(json_encode(['result' => 'empty_email'])); die(json_encode(['result' => 'empty_email']));
} }
// 이메일 형식 체크
if ($mem->email_format_check($email) === false) {
die(json_encode(['result' => 'email_format_wrong']));
}
// 이메일 중복 체크
if ($mem->email_exists($email)) { if ($mem->email_exists($email)) {
die(json_encode(['result' => 'fail'])); die(json_encode(['result' => 'fail']));
} else { } else {
die(json_encode(['result' => 'success'])); die(json_encode(['result' => 'success']));
} }
//
} else if ($mode == 'input') { // ======================
// 비밀번호 해시 처리 // 3. 실제 회원 가입 처리
// ======================
} else if ($mode === 'input') {
// 1) 필수값 서버 검증 (JS만 믿지 않기)
if ($id === '' || $password === '' || $email === '') {
redirect_with_error('아이디, 비밀번호, 이메일은 필수 입력 항목입니다.');
}
// 2) 비밀번호 규칙 서버 검증
if (!password_check($password)) {
redirect_with_error('비밀번호는 8자 이상이며, 대문자/소문자/숫자/특수문자를 모두 포함해야 합니다.');
}
// 3) 선택 항목 기본값 처리 (미입력 시 빈 문자열)
$name = $name ?? '';
$zipcode = $zipcode ?? '';
$addr1 = $addr1 ?? '';
$addr2 = $addr2 ?? '';
// 4) 비밀번호 해시 처리
$hash = password_hash($password, PASSWORD_DEFAULT); $hash = password_hash($password, PASSWORD_DEFAULT);
// 프로필 이미지 처리
// 5) 프로필 이미지 처리 (선택 항목)
$photo = ''; // 기본값: 빈 문자열 또는 'default.jpg' 등으로 변경 가능
if (
isset($_FILES['photo']) &&
$_FILES['photo']['error'] === UPLOAD_ERR_OK &&
is_uploaded_file($_FILES['photo']['tmp_name'])
) {
$tmparr = explode('.', $_FILES['photo']['name']); $tmparr = explode('.', $_FILES['photo']['name']);
$ext = end($tmparr); $ext = strtolower(end($tmparr)); // 확장자 소문자로 정리
// 허용 확장자
$allow_ext = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($ext, $allow_ext)) {
redirect_with_error('이미지 파일(jpg, jpeg, png, gif)만 업로드 가능합니다.');
}
// 저장 파일명: 아이디.확장자
$photo = $id . '.' . $ext; $photo = $id . '.' . $ext;
copy($_FILES['photo']['tmp_name'], "../data/profile/". $photo); // 저장 경로
$target_dir = "../data/profile/";
$target_path = $target_dir . $photo;
// 배열 생성 // 디렉터리가 없으면 생성
if (!is_dir($target_dir)) {
mkdir($target_dir, 0777, true);
}
// 파일 복사
if (!copy($_FILES['photo']['tmp_name'], $target_path)) {
// 복사 실패 시 기본값 유지
$photo = '';
}
}
// 6) DB insert에 넘길 배열 생성
$arr = [ $arr = [
'id' => $id, 'id' => $id,
'password' => $hash, 'password' => $hash,
@ -63,6 +150,22 @@ if ($mode == 'id_chk') {
'photo' => $photo 'photo' => $photo
]; ];
// 입력 메서드 실행 // 7) 회원 정보 저장
$mem->input($arr); $mem->input($arr);
// 8) 가입 성공 시, 이전 입력/에러 세션 정리
unset($_SESSION['join_old'], $_SESSION['join_error']);
// 9) 회원가입 완료 후 알림 + 홈(index.php) 이동
echo "<script>
alert('회원가입이 완료되었습니다.');
window.location.href = '/member/index.php';
</script>";
exit;
} }
// 기타 잘못된 접근에 대한 처리 (옵션)
// else {
// redirect_with_error('잘못된 접근입니다.');
// }