눈사람의 해킹공부

[PHP/MYSQL] 회원 전용 게시판 만들기 3. 게시글 보기, 작성, 수정, 삭제 본문

[PHP/MYSQL] 회원 전용 게시판 만들기 3. 게시글 보기, 작성, 수정, 삭제

5n0wman 2023. 11. 21. 16:53

 

안녕하세요 눈사람입니다. 저번 포스트에 이어 게시판에서 제목을 누르면 게시글을 볼 수 있는 페이지와, 게시글 작성, 수정, 삭제 페이지를 살펴보겠습니다.

 

먼저 게시글을 보는 페이지 view.php 입니다.

view.php

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/header.php";

$bid=$_GET["bid"];
$result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error);
$rs = $result->fetch_object();
?>
      <h3 class="pb-4 mb-4 fst-italic border-bottom" style="text-align:center;">
        - 게시판 보기 -
      </h3>

      <article class="blog-post">
        <h2 class="blog-post-title"><?php echo $rs->subject;?></h2>
        <p class="blog-post-meta"><?php echo $rs->regdate;?> by <a href="#"><?php echo $rs->userid;?></a></p>

        <hr>
        <p>
          <?php echo $rs->content;?>
        </p>
        <hr>
      </article>

      <nav class="blog-pagination" aria-label="Pagination">
        <a class="btn btn-outline-secondary" href="/index.php">목록</a>
        <a class="btn btn-outline-secondary" href="/reply.php?bid=<?php echo $rs->bid;?>">답글</a>
        <a class="btn btn-outline-secondary" href="/write.php?bid=<?php echo $rs->bid;?>">수정</a>
        <a class="btn btn-outline-secondary" href="/delete.php?bid=<?php echo $rs->bid;?>">삭제</a>
      </nav>

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/footer.php";
?>

view.php는 웹 기반의 게시판 시스템에서 특정 게시글을 보여주는 기능을 구현한 것입니다. 각 부분의 기능을 설명하겠습니다.

1. 게시글 데이터 가져오기

$bid = $_GET["bid"]; $result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error);
$rs = $result->fetch_object();
  • 사용자로부터 전달받은 bid(게시글 ID) 값을 사용하여 데이터베이스에서 해당 게시글을 조회합니다.
  • 조회 결과는 $rs 객체에 저장됩니다.

2. 게시글 표시

  • 게시글 제목($rs->subject), 등록 날짜($rs->regdate), 작성자 아이디($rs->userid), 내용($rs->content) 등을 웹 페이지에 표시합니다.

3. 네비게이션 버튼

  • '목록', '답글', '수정', '삭제' 등의 기능을 수행하는 버튼을 제공합니다. 각 버튼은 해당 기능을 수행하는 다른 PHP 페이지로의 링크를 포함합니다.

view.php

필자가 만든 계정으로 로그인 한 뒤에 index.php에서 글 제목을 클릭하여 넘어온 view.php 화면입니다.

이제 index.php에 게시글이 존재해야 view.php로 넘어올 수 있기 때문에 게시글을 작성해봐야겠죠?

 

게시글 작성 로직인 write.php를 알아보겠습니다.

wirte.php

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/header.php";

if(!isset($_SESSION['UID'])){
    echo "<script>alert('이 게시판은 회원 전용입니다.');history.back();</script>";
    exit;
}

$bid = isset($_GET["bid"]) ? $_GET["bid"] : null;
$subject = '';
$content = '';

if($bid){
    $result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error);
    $rs = $result->fetch_object();
    if(!$rs || $rs->userid != $_SESSION['UID']){
        echo "<script>alert('자신의 글이 아니면 편집할 수 없습니다.');history.back();</script>";
        exit;
    }
    if ($rs) {
        $subject = $rs->subject; // 데이터베이스에서 제목 할당
        $content = $rs->content; // 데이터베이스에서 내용 할당
    }
}
?>
<form method="post" action="write_ok.php">
    <input type="hidden" name="bid" value="<?php echo htmlspecialchars($bid);?>">
    <div class="mb-3">
        <label for="exampleFormControlInput1" class="form-label">제목</label>
        <input type="text" name="subject" class="form-control" id="exampleFormControlInput1" placeholder="제목을 입력하세요." value="<?php echo htmlspecialchars($subject); ?>">
    </div>
    <div class="mb-3">
        <label for="exampleFormControlTextarea1" class="form-label">내용</label>
        <textarea class="form-control" id="exampleFormControlTextarea1" name="content" rows="3"><?php echo htmlspecialchars($content); ?></textarea>
    </div>
    <button type="submit" class="btn btn-primary">등록</button>
</form>
<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/footer.php";
?>

write.php는 게시판 글쓰기 및 글 편집 기능을 처리합니다. 또한, 회원 전용 게시판에서 게시글을 작성하거나, 사용자가 작성한 기존의 게시글을 수정할 수 있는 기능을 제공합니다. 사용자가 로그인한 상태이며, 작성자 본인의 글만 편집할 수 있도록 검증하는 과정도 포함되어 있습니다. 여기에는 몇 가지 주요 기능과 검증 단계가 포함되어 있습니다.

1. 로그인 상태 검증

if(!isset($_SESSION['UID'])){ 
echo "<script>alert('이 게시판은 회원 전용입니다.');history.back();</script>"; 
exit; 
}
  • 사용자가 로그인하지 않았다면, 경고 메시지를 표시하고 이전 페이지로 돌아가게 합니다.

2. 게시글 정보 가져오기 및 수정 권한 검증

$bid = isset($_GET["bid"]) ? $_GET["bid"] : null;
...
if($bid){ 
	$result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error); 
	$rs = $result->fetch_object();
	if(!$rs || $rs->userid != $_SESSION['UID']){ 
	echo "<script>alert('자신의 글이 아니면 편집할 수 없습니다.');history.back();</script>";
    	exit; 
	} ... 
}
  • $_GET["bid"]를 통해 전달받은 게시글 ID(bid)를 사용하여 데이터베이스에서 해당 게시글을 조회합니다.
  • 만약 조회된 게시글이 없거나, 현재 로그인한 사용자가 게시글 작성자가 아닌 경우, 경고 메시지를 표시하고 이전 페이지로 돌아갑니다.

3. 폼 데이터 채우기

  • 조회된 게시글이 있을 경우, 제목($subject)과 내용($content)을 변수에 할당합니다.

4. 게시글 작성/편집 폼

<form method="post" action="write_ok.php"> ... </form>
  • 게시글 작성 또는 편집을 위한 폼을 표시합니다. 이 폼은 제목과 내용을 입력받아 write_ok.php로 전송합니다.
  • htmlspecialchars 함수를 사용하여 제목과 내용을 HTML 특수 문자로 변환함으로써 XSS(Cross-Site Scripting) 공격을 방지합니다.

이제 write.php에서 글 작성 폼을 입력받아 write_ok.php로 전송한 후에 write.php에서 어떻게 처리되는지 살펴봅시다.

write_ok.php

<?php session_start();
include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";//dbcon.php 안에는 session_start()가 없기때문에 위에 따로 선언해준다.
if(!$_SESSION['UID']){
    echo "<script>alert('회원 전용 게시판입니다.');location.href='/index.php';</script>";
    exit;
}

$subject=$_POST["subject"];
$content=$_POST["content"];
$userid=$_SESSION['UID'];//userid는 세션값으로 넣어준다.
$status=1;//status는 1이면 true, 0이면 false이다.

$sql="insert into board (userid,subject,content) values ('".$userid."','".$subject."','".$content."')";
$result=$mysqli->query($sql) or die($mysqli->error);

if($result){
    echo "<script>location.href='/index.php';</script>";
    exit;
}else{
    echo "<script>alert('글등록에 실패했습니다.');history.back();</script>";
    exit;
}
?>

write_ok.php는 write.php에서 받아온 폼을 데이터베이스에 등록하는 기능을 구현합니다. 스크립트의 각 부분은 다음과 같은 역할을 수행합니다.

1. 세션 시작 및 데이터베이스 연결 파일 포함

<?php session_start(); 
include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";
  • session_start(): 사용자의 세션을 시작합니다. 이는 사용자의 로그인 상태를 추적하는 데 필요합니다.
  • include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";: 서버의 루트 디렉토리에 위치한 dbcon.php 파일을 포함합니다.

2. 로그인 상태 검증

if(!$_SESSION['UID']){ 
	echo "<script>alert('회원 전용 게시판입니다.');location.href='/index.php';</script>"; 
	exit;
}
  • 사용자가 로그인하지 않은 경우, '회원 전용 게시판입니다.'라는 메시지를 표시하고 메인 페이지(/index.php)로 리디렉션합니다.

3. 게시글 정보 수집

$subject = $_POST["subject"]; 
$content = $_POST["content"]; 
$userid = $_SESSION['UID'];
  • 사용자가 입력한 게시글의 제목(subject)과 내용(content)을 받아옵니다.
  • 게시글 작성자의 아이디(userid)는 현재 로그인한 사용자의 세션에서 가져옵니다.

4. 데이터베이스에 게시글 등록

$sql = "insert into board (userid,subject,content) values ('".$userid."','".$subject."','".$content."')"; 
$result = $mysqli->query($sql) or die($mysqli->error);
  • INSERT INTO SQL 명령을 사용하여 board 테이블에 새로운 게시글을 추가합니다. 이때, 사용자 아이디, 제목, 내용을 데이터베이스에 저장합니다.

5. 결과 처리 및 사용자 리디렉션

if($result){ 
	echo "<script>location.href='/index.php';</script>"; 
} else { 
	echo "<script>alert('글등록에 실패했습니다.');history.back();</script>"; 
}
  • 게시글 등록이 성공하면 사용자를 메인 페이지(/index.php)로 리디렉션합니다.
  • 등록에 실패한 경우 '글등록에 실패했습니다.'라는 메시지를 표시하고 이전 페이지로 돌아갑니다.

이제 view.php에서 게시글 삭제 버튼을 누르면 동작하는 delete.php를 같이 살펴보겠습니다.

delete.php

<?php session_start();
include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";

if(!$_SESSION['UID']){
    echo "<script>alert('회원 전용 게시판입니다.');location.href='/index.php';</script>";
    exit;
}

$bid=$_POST["bid"]??$_GET["bid"];//post가 아니면 get으로 받는다

if($bid){
    $result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error);
    $rs = $result->fetch_object();

    if($rs->userid!=$_SESSION['UID']){
        echo "<script>alert('본인 글이 아니면 삭제할 수 없습니다.');location.href='/';</script>";
        exit;
    }

    $sql="update board set status=0 where bid=".$bid;//status값을 바꿔준다.
    $result=$mysqli->query($sql) or die($mysqli->error);
}else{
    echo "<script>alert('삭제할 수 없습니다.');history.back();</script>";
    exit;
}


if($result){
    echo "<script>alert('삭제했습니다.');location.href='/index.php';</script>";
    exit;
}else{
    echo "<script>alert('글삭제에 실패했습니다.');history.back();</script>";
    exit;
}
?>

delete.php는 웹사이트의 게시판에서 특정 게시글을 삭제하는 기능을 처리합니다. 스크립트의 각 부분은 다음과 같은 역할을 수행합니다.

1. 세션 시작 및 데이터베이스 연결 파일 포함

<?php session_start(); include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";
  • session_start(): 사용자의 세션을 시작합니다. 이는 사용자의 로그인 상태를 추적하는 데 필요합니다.
  • include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";: 서버의 루트 디렉토리에 위치한 dbcon.php 파일을 포함합니다.

2. 로그인 상태 검증

if(!$_SESSION['UID']){ 
	echo "<script>alert('회원 전용 게시판입니다.');location.href='/index.php';</script>"; 
	exit; 
}
  • 사용자가 로그인하지 않은 경우, 경고 메시지를 표시하고 메인 페이지(/index.php)로 리디렉션합니다.

3. 게시글 ID 처리

$bid = $_POST["bid"] ?? $_GET["bid"]; // POST가 아니면 GET으로 받는다
  • 게시글 ID(bid)를 $_POST 또는 $_GET 배열에서 가져옵니다. 이는 폼 데이터나 URL 파라미터를 통해 전달될 수 있습니다.

4. 게시글 삭제 권한 검증 및 처리

if($bid){ 
	... 
    if($rs->userid != $_SESSION['UID']){ 
    ... 
    } 
    
	$sql = "update board set status=0 where bid=".$bid; // status값을 바꿔준다. 
    ... 
}
  • bid가 존재할 경우, 해당 ID의 게시글을 데이터베이스에서 조회합니다.
  • 게시글 작성자가 현재 로그인한 사용자와 다른 경우, 경고 메시지를 표시하고 홈페이지(/)로 리디렉션합니다.
  • 게시글 작성자가 현재 로그인한 사용자와 같은 경우, board 테이블에서 해당 게시글의 status를 0으로 설정하여 게시글을 "삭제" 처리합니다.

5. 결과 처리 및 사용자 리디렉션

if($result){ 
	echo "<script>alert('삭제했습니다.');location.href='/index.php';</script>"; 
} else { 
	echo "<script>alert('글삭제에 실패했습니다.');history.back();</script>"; 
}
  • 게시글 삭제(업데이트) 작업이 성공하면 사용자에게 알림을 표시하고 메인 페이지(/index.php)로 리디렉션합니다.
  • 삭제 작업이 실패한 경우, 경고 메시지를 표시하고 이전 페이지로 돌아갑니다.

 

다음 포스트에는 게시물 검색기능과 답글 기능, 그리고 페이징에 대해 알아보도록 하겠습니다.