
1달차 2주차 과제는 다음 4가지와 같다.
- 복습 (Database, SQL)
- Mini Mission (점수 확인 페이지 제작)
- 회원가입 페이지 만들기 (기능 구현)
- 로그인 페이지 DB 연동하기
+ 마이페이지 개발
1번 복습 내용은 "스터디 정리" 카테고리에 기록해두었다.
따라서 2번 과제부터 정리하였다.
get 방식으로 이름을 입력받아, 해당하는 학생의 점수를 출력해주는 페이지를 제작하는 과제이다.
학생의 이름을 입력받는 페이지, 데이터를 처리하여 점수를 출력하는 페이지 2개로 나누어 제작하였다.
1) 이름 입력 페이지
이 페이지에서 필요한 요소는 이름을 입력하는 칸과 확인 버튼이다.
이 요소들을 생성하는 코드는 아래와 같다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Score</title>
</head>
<body>
<form name="score" method="get" action="score_proc.php">
<span>이름</span>
<input name="name">
<button type="submit">확인</button>
</form>
</body>
</html>
| score.html 페이지 결과 |
|---|
![]() |
| ○ 이름 입력칸에 이름을 입력하면 파라미터가 GET방식으로 score_proc.php 로 전달된다. |
2) 데이터 처리 & 점수 출력 페이지
앞선 score.html 을 통해 전달된 이름을 바탕으로 DB를 조회하여, 점수를 출력해주는 페이지이다.
핵심 코드는 아래와 같다.
<?php
$name = $_GET['name'];
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "select score from score where name='$name'";
$result = mysqli_query($con, $sql);
$match = mysqli_num_rows($result);
if (!$match) {
echo "<script>
window.alert('등록되지 않는 이름입니다')
history.go(-1)
</script>";
exit;
}
$row = mysqli_fetch_assoc($result);
$score = $row["score"];
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Score</title>
</head>
<body>
<span>점수</span>
<span><?=$score?> 점</span>
</body>
</html>
| score_proc.php 페이지 결과 |
|---|
![]() |
| ○ $name 변수에 GET방식으로 전달받은 이름을 대입한다. |
| ● DB에 로그인 후, 전달받은 파라미터와 같은 이름의 점수를 가져온다. |
| ○ 만약, 이름이 존재하지 않는다면, 알림을 띄우고 login.html로 돌아간다. |
| ● 만약, DB에 이름이 존재한다면, 가져온 결과에서 점수를 추출하여 화면에 출력한다. |
회원가입은 폼 양식에 사용자가 입력한 아이디, 비밀번호, 이메일 등의 회원정보를 DB에 저장하는 페이지이다. 여기서 아이디 입력 시 기존에 등록된 아이디와 중복되지 않는지를 체크한다.
1) 회원 DB테이블
회원가입 정보를 저장하기 위한 DB 테이블의 구조는 다음과 같다.
![]() |
|---|
| ● 레코드 번호, 아이디, 비밀번호, 이름, 이메일 주소, 회원가입일, 레벨, 포인트 필드가 존재한다. |
| ○ num, id, pass, name 필드는 필수 입력 항목이므로 not null로 설정하였다. |
| ● 레코드 번호를 의미하는 num 필드는 auto_increment와 primary key로 설정된다. |
2) 회원가입 폼 양식
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>회원가입</title>
<link rel="stylesheet" href="style.css">
<script>
function check_input() {
if (!document.member.id.value) {
alert("아이디를 입력하세요!");
document.member.id.focus();
return;
}
if (!document.member.pass.value) {
alert("비밀번호를 입력하세요!");
document.member.pass.focus();
return;
}
if (!document.member.pass_confirm.value) {
alert("비밀번호 확인을 입력하세요!");
document.member.pass_confirm.focus();
return;
}
if (!document.member.name.value) {
alert("이름을 입력하세요!");
document.member.name.focus();
return;
}
if (!document.member.email.value) {
alert("이메일 주소를 입력하세요!");
document.member.email.focus();
return;
}
if (document.member.pass.value != document.member.pass_confirm.value) {
alert("비밀번호가 일치하지 않습니다.\n다시 입력해 주세요!");
document.memeber.pass.focus();
document.memeber.pass.select();
return;
}
document.member.submit();
}
function reset_form() {
document.member.id.value="";
document.member.pass.value="";
document.member.pass_confirm.value="";
document.member.name.value="";
document.member.email.value="";
document.member.id.focus();
return;
}
function check_id() {
window.open("check_id.php?id="+document.member.id.value, "IDcheck", "left=700, top=300, width=380, height=160, scrollbars=no, resizable=yes");
}
</script>
</head>
<body>
<form name="member" action="insert.php" method="post">
<h2>회원 가입</h2>
<ul class="join_form">
<li>
<span class="col1">아이디</span>
<span class="col2"><input name="id"></span>
<span class="col3"><button type="button" onclick="check_id()">중복체크</button></span>
</li>
<li>
<span class="col1">비밀번호</span>
<span class="col2"><input type="password" name="pass"></span>
</li>
<li>
<span class="col1">비밀번호 확인</span>
<span class="col2"><input type="password" name="pass_confirm"></span>
</li>
<li>
<span class="col1">이름</span>
<span class="col2"><input name="name"></span>
</li>
<li>
<span class="col1">이메일</span>
<span class="col2"><input name="email"></span>
</li>
</ul>
<ul class="buttons">
<li><button type="button" onclick="check_input()">저장하기</button></li>
<li><button type="button" onclick="reset_form()">취소하기</button></li>
</ul>
</form>
</body>
</html>
| 실행 결과 |
|---|
![]() |
| ○ '회원가입' 버튼을 클릭하면 자바스크립트 check_input() 함수를 통해 폼 내용이 전부 입력되었는지 체크한다. |
| ● '취소하기' 버튼을 클릭하면 reset_form() 함수를 통해 입력 데이터가 초기화된다. |
| ○ '중복체크' 버튼을 클릭하면 check_id() 함수를 통해 아이디가 중독되는지 체크한다. |
| ● 모든 양식이 입력되었다면, 데이터를 처리하는 insert.php 페이지로 이동된다. |
위의 코드는 스크립트를 지운다면, 양식이 전부 입력되지 않아도 회원가입이 되는 취약점이 존재한다.
따라서 후에 insert.php 백엔드 측에서 한번 더 검증하는 코드를 추가하였다.
3) 아이디 중복 체크
위의 아이디 양식 페이지에서 '중복 체크' 버튼을 클릭하면, check_id() 함수가 실행되며 이 함수 내에 있는 window.open()에 의해 새로운 창이 열린다. 또한 입력된 id를 매개변수로 전달받게 된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.close {margin:20px 0 0 120px; cursor: pointer;}
</style>
</head>
<body>
<h3>아이디 중복체크</h3>
<div>
<?php
$id = $_GET["id"];
if(!$id)
echo ("아이디를 입력해주세요!");
else {
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "select * from members where id='$id'";
$result = mysqli_query($con, $sql);
$num_record = mysqli_num_rosw($result);
if ($num_record) {
echo $id."아이디는 이미 사용중입니다<br>";
echo "다른 아이디를 입력해주세요!<br>";
}
else
echo $id."아이디는 사용 가능합니다.<br>";
}
mysqli_close($con);
?>
</div>
<div class="close">
<button onclick="javascript:self.close()">창닫기</button>
</div>
</body>
</html>
[경우에 따른 윈도우 창 화면을 아래에 나타내었다]
| 아이디 미입력시 | 아이디 중복시 | 아이디 사용 가능 |
|---|---|---|
![]() | ![]() | ![]() |
| ○ 회원 가입 폼 양식에서 사용자가 입력한 값을 GET방식으로 전달받아 $id에 저장한다. |
|---|
| ● MySQL 데이터베이스에 접속하여 id의 필드값이 $id인 레코드를 검색하여 중복되는지 검사한다. |
4) DB에 회원 정보 저장
회원 가입 폼 양식에서 사용자가 회원 정보를 입력 후 '회원가입' 버튼을 눌렀을때 회원 정보를 DB에 저장하는 페이지이다.
<?php
$id = $_POST["id"];
$pass = $_POST["pass"];
$name = $_POST["name"];
$email = $_POST["email"];
$regist_day = date("Y-m-d (H:i)");
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "insert into members (id, pass, name, email, regist_day, level, point) ";
$sql .= "values ('$id', '$pass', '$name', '$email', '$regist_day, 1, 0)";
mysqli_query($con, $sql);
mysqli_close($con);
echo "<script>location.href='login_form.php';</script>";
?>
| 회원가입 양식 작성 후 회원가입 클릭 | 데이터베이스에 회원 정보 추가 완료 |
|---|---|
![]() | ![]() |
로그인 페이지는 사용자가 회원가입 시 사용한 아이디와 비밀번호를 입력하여 사이트에 접속하도록 해준다. 세션을 이용하여 로그인 기능을 구현하였다.
1) 로그인 페이지
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>로그인</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script>
function check_input() {
if (!document.login.id.value) {
alert("아이디를 입력하세요");
document.login_form.id.focus();
return;
}
if (!document.login.pass.value) {
alert("비밀번호를 입력하세요");
document.login_form.pass.focus();
return;
}
document.login.submit();
}
</script>
</head>
<body>
<h2 class="login_title">로그인</h2>
<form name="login" method="post" action="login.php">
<ul class="login_form">
<li>
<span class="col1">아이디</span>
<span class="col2"><input name="id" placeholder="아이디"></span>
</li>
<li>
<span class="col1">비밀번호</span>
<span class="col2"><input type="password" name="pass" placeholder="비밀번호"></span>
</li>
<li><button type="button" onclick="check_input()">로그인</button></li>
</ul>
</form>
</body>
</html>
| 실행결과 |
|---|
![]() |
2) 로그인 처리 페이지
로그인 페이지에서 아이디와 비밀번호를 입력 후 로그인 하면, DB에 접속하여 동일한 계정의 레코드가 있는지 판단하여 존재한다면 세션을 등록한다.
이후 이 세션 정보를 이용하여 로그인 상태인지 아닌지 판단할 수 있게 된다.
<?php
$id = $_POST["id"];
$pass = $_POST["pass"];
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "select * from members where id='$id'";
$result = mysqli_query($con, $sql);
$num_match = mysqli_num_rows($result);
if (!$num_match) {
echo "<script>
window.alert('등록되지 않은 아이디입니다!')
history.go(-1)
</script>";
}
else {
$row = mysqli_fetch_assoc($result);
$db_pass = $row["pass"];
mysqli_close($con);
if($pass != $db_pass) {
echo "<script>
window.alert('비밀번호가 틀립니다!')
history.go(-1)
</script>";
exit;
}
else {
session_start();
$_SESSION["userid"] = $row["id"];
$_SESSION["username"] = $row["name"];
echo "<script>location.href='index.php';</script>";
}
}
3) 로그인 상태 판별
login.php에서 사용자가 입력한 아이디와 비밀번호가 DB에 있는 정보와 일치한다면, 세션변수 $_SESSION["userid"]와 $_SESSION["username"]을 등록하였다.
이 두 세션 변수를 이용하여 로그인 상태를 판별할 수 있고, 그에 따라 메뉴를 다르게 표시할 수 있다.
로그인 상태를 판별하는 코드는 다음과 같다.
<?php
session_start();
if (isset($_SESSION["userid"]))
$userid = $_SESSION["userid"];
else
$userid = "";
if (isset($_SESSION["username"]))
$username = $_SESSION["username"];
else
$username = "";
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>메인페이지</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<h3 class="logo">
<a href="index.php">취업반스터디</a>
</h3>
<div class="top">
<?php
if (!$userid) {
?>
<span><a href="form.php">회원가입</a></span>
<span> | </span>
<span><a href="login_form.php">로그인</a></span>
<?php
}
else {
$logged = $username."(".$userid.")";
?>
<span><?=$logged?></span>
<span> | </span>
<span><a href="logout.php">로그아웃</a></span>
<span> | </span>
<span><a href="modify_form.php">마이 페이지</a></span>
<?php
}
?>
</div>
</div>
</body>
</html>
| 비로그인 상태 (세션 X) | 로그인 상태 (세션 O) |
|---|---|
![]() | ![]() |
| 로그인 이전상태이므로, 회원가입과 로그인 메뉴 표시 | 로그인 상태이므로, 사용자 정보와 로그아웃, 마이페이지 메뉴 표시 |
이렇게 '로그인 페이지에 DB연동하기' 과제가 완료되었다.
마이페이지에서는 사용자가 회원가입 시에 기입한 정보를 보여주고, 정보를 변경할 수 있는 기능을 추가하였다.
1) 마이페이지
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>마이페이지</title>
<link rel="stylesheet" href="style.css">
<script>
function check_input() {
if (!document.member.pass.value) {
alert("비밀번호를 입력하세요!");
document.member.pass.focus();
return;
}
if (!document.member.pass_confirm.value) {
alert("비밀번호 확인을 입력하세요!");
document.member.pass_confirm.focus();
return;
}
if (!document.member.name.value) {
alert("이름을 입력하세요!");
document.member.name.focus();
return;
}
if (!document.member.email.value) {
alert("이메일 주소를 입력하세요!");
document.member.email.focus();
return;
}
if (document.member.pass.value != document.member.pass_confirm.value) {
alert("비밀번호가 일치하지 않습니다.\n다시 입력해 주세요!");
document.memeber.pass.focus();
document.memeber.pass.select();
return;
}
document.member.submit();
}
function reset_form() {
document.member.id.value="";
document.member.pass.value="";
document.member.pass_confirm.value="";
document.member.name.value="";
document.member.email.value="";
document.member.id.focus();
return;
}
</script>
</head>
<body>
<?php
session_start();
if (isset($_SESSION['userid']))
$userid = $_SESSION['userid'];
else
$userid = '';
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "select * from members where id='$userid'";
$result = mysqli_query($con, $sql);
$num_record = mysqli_num_rows($result);
if (!num_record) {
echo "<script>
window.alert('로그인이 필요합니다!')
location.href='login_form.php';
</script>";
exit;
}
$row = mysqli_fetch_assoc($result);
$pass = $row["pass"];
$name = $row["name"];
$email = $row["email"];
mysqli_close($con);
?>
<form name="member" action="modify.php?id=<?=$userid?>" method="post">
<h2>마이 페이지</h2>
<ul class="join_form">
<li>
<span class="col1">아이디</span>
<span class="col2"><?=$userid?></span>
</li>
<li>
<span class="col1">비밀번호</span>
<span class="col2"><input type="password" name="pass" value="<?=$pass?>"></span>
</li>
<li>
<span class="col1">비밀번호 확인</span>
<span class="col2"><input type="password" name="pass_confirm"></span>
</li>
<li>
<span class="col1">이름</span>
<span class="col2"><input name="name" value="<?=$name?>"></span>
</li>
<li>
<span class="col1">이메일</span>
<span class="col2"><input name="email" value="<?=$email?>"></span>
</li>
</ul>
<ul class="buttons">
<li><button type="button" onclick="check_input()">저장하기</button></li>
<li><button type="button" onclick="reset_form()">취소하기</button></li>
</ul>
</form>
</body>
</html>
| 실행 결과 |
|---|
![]() |
| ○ 스크립트 코드는 회원가입 페이지와 같이 양식이 작성되었는지 확인용이다. |
| ● 세션에 저장된 정보를 바탕으로 $userid에 id값을 지정한다. |
| ○ 만약 세션이 존재하지 않는다면(비로그인 상태), 로그인이 필요하다는 알림을 띄우고 로그인 페이지로 이동된다. |
| ● $userid와 일치하는 id를 갖는 레코드를 DB에서 불러와 각 입력칸에 value 값으로 정보를 표시한다. |
2) 정보 변경시 DB 내용 변경 처리
마이페이지에서 정보를 변경 후, '저장하기' 버튼을 클릭하면 해당 내용으로 DB의 정보가 변경되어야 한다.
이렇게 DB 수정을 처리하는 modify.php의 코드는 다음과 같다.
<?php
$id = $_GET["id"];
$pass = $_POST["pass"];
$name = $_POST["name"];
$email = $_POST["email"];
$con = mysqli_connect("localhost", "user", "12345", "sample");
$sql = "update members set pass='$pass', name='$name', email='$email'";
$sql .= " where id='$id'";
mysqli_query($con, $sql);
mysqli_close($con);
echo "<script>
window.alert('정보 수정 완료!')
location.href='modify_form.php';
</script>";
?>
여기서는 update 명령을 사용하여 기입된 정보를 바탕으로 DB테이블의 내용을 수정한다
update 명령의 사용 형식은 다음과 같다.
update 테이블명 set 필드1=값, 필드2=값, ... where 조건식;
| 기존 admin 정보 |
|---|
![]() |
| 수정 할 admin 정보 | 수정 후 DB 정보 |
|---|---|
![]() | ![]() |
그런데 위의 코드에서도 취약점을 발견할 수 있다.
마이 페이지 창에서 정보를 수정해서 modify.php를 요청하는 것이 아닌, URL로 modify.php?id=@ 를 입력하는 경우 이를 검증하지 못하고 수정이 되어버려, 해당되는 id의 컬럼 정보들이 NULL이 되어버린다.
[실행결과]
![]() | ![]() |
|---|---|
| URL로 id파라미터를 넣어 수정처리 페이지 요청 | 비밀번호, 이름, 이메일은 전달받지 못해 널('')로 수정되었음 |
따라서 수정페이지에서 수정한것이 아니라면, update가 되지 않도록 해주어야 한다.
이를 위해 아래의 코드를 중간에 추가해주었다.
if (!$pass or !$name or !$email) {
echo "<script>
window.alert('미입력된 정보가 있어 수정이 불가합니다!')
history.go(-1);
</script>";
exit;
}
이렇게 해주면 정보가 업데이트 되지 않고, 알림창을 띄운 뒤 이전 페이지로 돌아가게 된다.