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

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;
}
// 이메일 형식 체크
public function email_format_check($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
public function email_exists($email) {
$sql = "SELECT * FROM member WHERE email=:email";
$stmt = $this->conn->prepare($sql);

View File

@ -78,71 +78,91 @@ document.addEventListener("DOMContentLoaded", () => {
} else if (data.result == 'empty_id') {
alert('이메일이 입력되지 않았습니다.')
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", () => {
const f = document.input_form
if (f.id.value == '') {
alert('아이디를 입력해 주세요.')
f.id.focus()
return false
const f = document.input_form;
if (f.id.value.trim() === '') {
alert('아이디를 입력해 주세요.');
f.id.focus();
return false;
}
// 아이디 중복 체크 여부
if (f.id_chk.value == 0) {
alert('아이디 중복확인이 필요합니다.')
return false
if (f.id_chk.value === "0") {
alert('아이디 중복확인이 필요합니다.');
return false;
}
// 비밀번호 입력 여부
if (f.password.value == '') {
alert('비밀번호를 입력하세요.')
f.password.focus()
return false
if (f.password.value === '') {
alert('비밀번호를 입력하세요.');
f.password.focus();
return false;
}
if (f.password2.value == '') {
alert('비밀번호 확인이 필요합니다.')
f.password2.focus()
return false
if (f.password2.value === '') {
alert('비밀번호 확인이 필요합니다.');
f.password2.focus();
return false;
}
// ★ 비밀번호 규칙 검사 추가 (여기)
if (!passwordRule.test(f.password.value)) {
alert('비밀번호는 8자 이상이며, 대문자/소문자/숫자/특수문자를 모두 포함해야 합니다.');
f.password.focus();
return false;
}
// 비밀번호 일치 여부
if (f.password.value != f.password2.value) {
alert('비밀번호가 일치하지 않습니다.')
//f.password.value = ''
f.password2.value = ''
f.password2.focus()
return false
if (f.password.value !== f.password2.value) {
alert('비밀번호가 일치하지 않습니다.');
// f.password.value = '';
f.password2.value = '';
f.password2.focus();
return false;
}
// 이름 등록 여부
if (f.name.value == '') {
alert('이름을 입력해 주세요.')
f.name.focus()
return false
if (f.name.value.trim() === '') {
alert('이름을 입력해 주세요.');
f.name.focus();
return false;
}
// 이메일 등록 여부
if (f.email.value == '') {
alert('이메일을 입력해 주세요')
f.email.focus()
return false
if (f.email.value.trim() === '') {
alert('이메일을 입력해 주세요');
f.email.focus();
return false;
}
// 이메일 중복 체크 여부
if(f.email_chk.value == 0) {
alert('이메일 중복확인이 필요합니다.')
return false
if (f.email_chk.value === "0") {
alert('이메일 중복확인이 필요합니다.');
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="flex-grow-1">
<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>
<button type="button" class="btn btn-secondary" id="btn_id_check"> 아이디 중복확인 </button>
</div>
@ -48,14 +48,14 @@ include 'header.php';
<div class="d-flex mt-3 gap-2 align-items-end">
<div class="w-50">
<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 class="d-flex mt-3 gap-2 align-items-end">
<div class="flex-grow-1">
<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>
<button type="button" id="btn_email_check" class="btn btn-secondary"> 이메일 중복확인 </button>
</div>
@ -71,11 +71,11 @@ include 'header.php';
<div class="d-flex mt-3 gap-2 justify-content-between">
<div class="w-50">
<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 class="w-50">
<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>

View File

@ -1,57 +1,144 @@
<?php
// 맨 첫 줄들에 추가
// 개발 단계: 에러 표시
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// 세션 시작
session_start();
include '../config/dbconfig.php'; // 상대경로
include '../config/member.php';
$mem = new Member($db);
$id = (isset($_POST['id']) && $_POST['id'] != '') ? $_POST['id'] : '';
$password = (isset($_POST['password']) && $_POST['password'] != '') ? $_POST['password'] : '';
$email = (isset($_POST['email']) && $_POST['email'] != '') ? $_POST['email'] : '';
$name = (isset($_POST['name']) && $_POST['name'] != '') ? $_POST['name'] : '';
$zipcode = (isset($_POST['zipcode']) && $_POST['zipcode'] != '') ? $_POST['zipcode'] : '';
$addr1 = (isset($_POST['addr1']) && $_POST['addr1'] != '') ? $_POST['addr1'] : '';
$addr2 = (isset($_POST['addr2']) && $_POST['addr2'] != '') ? $_POST['addr2'] : '';
$mode = (isset($_POST['mode']) && $_POST['mode'] != '') ? $_POST['mode'] : '';
// ===== 공통 입력값 수집 =====
$id = isset($_POST['id']) ? trim($_POST['id']) : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
$zipcode = isset($_POST['zipcode']) ? trim($_POST['zipcode']) : '';
$addr1 = isset($_POST['addr1']) ? trim($_POST['addr1']) : '';
$addr2 = isset($_POST['addr2']) ? trim($_POST['addr2']) : '';
$mode = isset($_POST['mode']) ? trim($_POST['mode']) : '';
// 아이디 중복 체크
if ($mode == 'id_chk') {
if ($id == '') {
// ===== 비밀번호 규칙 서버 검증 함수 =====
// 최소 8자, 소문자/대문자/숫자/특수문자 각 1개 이상
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']));
}
if ($mem->id_exists($id)) {
die(json_encode(['result' => 'fail']));
} else {
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']));
}
// 이메일 형식 체크
if ($mem->email_format_check($email) === false) {
die(json_encode(['result' => 'email_format_wrong']));
}
// 이메일 중복 체크
if ($mem->email_exists($email)) {
die(json_encode(['result' => 'fail']));
} else {
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);
// 프로필 이미지 처리
// 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']);
$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;
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 = [
'id' => $id,
'password' => $hash,
@ -63,6 +150,22 @@ if ($mode == 'id_chk') {
'photo' => $photo
];
// 입력 메서드 실행
// 7) 회원 정보 저장
$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('잘못된 접근입니다.');
// }