6주차 과제(WEB)

Peroro·2023년 5월 6일
0
post-thumbnail
post-custom-banner

이전 과제: https://velog.io/@azurp158/5주차-과제WEB1

6주차 과제

  • 게시글 수정
  • 게시글 삭제
  • 게시글 검색

지난 주에 이어서 기능을 하나씩 추가한 모습이다. 지난주에 부족했던 부분을 해결함과 동시에 기능을 추가했다.

read_index.php에서 여러 게시글이 목록에 올라오지 않고 하나만 올라와 있다.
read.js에 문제가 생겼는지 수정과 삭제가 되지 않는다.
update할 때 db의 board table이 갱신되게 설정을 했는지 게시판을 열 때마다 날짜가 바뀐다.
//해결책
- 쿼리문을 이중으로 썼던것이 문제였다. 하나만 사용하자 문제가 해결되었다.
- bid를 받아오고 나서 isset함수가 문제와 php 구문에서 ;를 빼먹었던 점이 있었다.
isset 대신 empty 함수를 사용했고, php 구문도 수정했다.
- Timestamp를 사용하는 date column에서 문제가 있었다.
조회를 하게되면 조회수에 대해서 update를 하게 되는데,
이때 date column에 update를 할때에도 date를 update하게 설정했기 때문이었다.

결과물

게시글 수정

  • 로그인을 했을 때, 게시판에서 제목을 누르게 되면 read.php로 이동하게 된다.

  • 수정버튼을 누르니, write.php로 이동하게 된다. 이때 GET 메서드로 bid 파라미터로 10을 전송해 10번에 해당하는 게시글에 대한 제목과 내용이 출력된다. 작성을 누른다면 write.php에서 했던 것처럼 변경이 된다.

게시글 삭제

  • 삭제 버튼을 눌렀을 때 정상적으로 삭제되었음을 알 수 있다.

게시글 탐색

  • est를 입력하자 해당 문자열이 존재하는 제목이 모두 출력되는 것을 알 수 있다.

코드

  • 이전 5주차에 코드를 제대로 올린 것 같지 않아 관련된 모든 코드를 올리겠다.
  • 먼저 게시판과 관련된 코드를 먼저 올리겠다.(게시글 검색 포함)
//read_index.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./read_index.js"></script>
</head>
<body onload="findboard()">// 처음에 실행되자마자 게시글을 불러온다.
    <?php
        session_start();
        if(!isset($_SESSION['id'])){?>
            <input type="button" name = "login" id = "login" value="login" onclick = gotologin()><?php
        }
        else{?>
            <input type="post" name = "write" id = "write" value = "write" onclick = gotowrite()><?php
        }
    ?>
    <table>
    <thead>
        <tr>
            <td width="70">번호</td>
            <td width="500">제목</td>
            <td width="120">글쓴이</td>
            <td width="100">작성일</td>
            <td width="100">조회수</td>
        </tr>
    </thead>
    <tbody name = "result" id = "result">
    </tbody>
    </table>
    <input type="text" name="word" id="word">
    <input type="submit" value="" onclick="findboard()">
</body>
</html>
//read_index.js
function gotowrite(){
    location.href = "write.php";
}
function gotologin(){
    location.href = "login.php";
}
function findboard(){//게시글 목록을 불러오는 함수이다. Ajax를 이용한다.
        const word = document.getElementById('word').value;
        const query = `SELECT bid, id, title, created, hit FROM board WHERE title LIKE '%${word}%' ORDER BY bid DESC LIMIT 0,10`;
        
        // Ajax 요청 보내기
        const xhr = new XMLHttpRequest();
        xhr.open('GET', '/get_read_index.php?query=' + encodeURIComponent(query));
        xhr.onreadystatechange = function() {
          if (xhr.readyState === 4 && xhr.status === 200) {
            const response = JSON.parse(xhr.responseText);
            
            // 응답 데이터 처리하기
            updateUI(response);
          }
        };
        xhr.send();
}

function updateUI(response){// DB로부터 받아온 정보를 이용해 UI를 업데이트 하는 함수다.
    const tableBodyElement = document.getElementById('result');
    tableBodyElement.innerHTML = ''; // 테이블 본문 요소 초기화
  
    for (const record of response) {
      const rowElement = document.createElement('tr'); // 새로운 tr 요소 생성
      const BID = document.createElement('td'); 
      const ID = document.createElement('td');
      const TITLE = document.createElement('td');
      const DATE = document.createElement('td');
      const HIT = document.createElement('td');
      BID.textContent = record.bid;
      ID.textContent = record.id;
      TITLE.textContent = record.title;
      DATE.textContent = record.date;
      HIT.textContent = record.hit;// td 요소에 데이터 설정
      rowElement.appendChild(BID); 
      rowElement.appendChild(TITLE);
      rowElement.appendChild(ID);
      rowElement.appendChild(DATE);
      rowElement.appendChild(HIT);// td 요소를 tr 요소에 추가;
      tableBodyElement.appendChild(rowElement); // tr 요소를 테이블 본문 요소에 추가
      TITLE.addEventListener('click', function(){
            location.href = "read.php?bid=" + record.bid;
      })
    }
}
//get_read_index.php
//AJAX 요청을 처리하는 부분이다.(서버측)
<?php
        $conn = new mysqli('localhost', 'conn', 'Testnote!%89','test');
        $q = $_GET['query'];
        $result = $conn->query($q);
        $rows = array();

        while($row = $result->fetch_array(MYSQLI_ASSOC)) {
            $rows[] = $row;
        }

        header('Content-Type: application/json');
        echo json_encode($rows);
    ?>
  • get_read_index.php의 경우 이전에 주소 찾기할 때 사용했던 get_address 부분과 완전히 똑같았다. 세부적인 쿼리문을 만드는 측은 클라이언트 측이기 때문이다.
  • 두 파일을 통합한다면 편할 것 같지만, 취약점이 될 수도 있을 것 같아 일단 그대로 두겠다.

  • 다음은 게시글 읽기에 관련된 코드를 올리겠다.
//read.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="read.js"></script>
    <style>
		h2 {text-align: center;}
		h5 {text-align: right;}
		h4 {text-align: left;}
	</style>
</head>
<body>
    <?php
    session_start();
    $id = '';
    if(isset($_SESSION['id'])){
        $id = $_SESSION['id'];
    }
    $bid = $_GET['bid'];
    $mysqli = new mysqli('localhost', 'conn', 'Testnote!%89', 'test');

    $q = "UPDATE board SET hit = hit + 1 where bid = $bid";
    $result = $mysqli->query($q);

    $q = "SELECT * from board WHERE bid = '$bid'";
    $result = $mysqli->query($q);
    $row = $result->fetch_array(MYSQLI_ASSOC);

    if($id == $row['id']){?>
        <form>
        <input type="hidden" name = "bid" id = "bid" value = <?php echo $bid;?> >
        <input type="button" name = "modify" id = "modify" value = "수정" onclick="modify_board();">
        <Input type="button" name = "remove" id = "remove" value = "삭제" onclick="remove_board();">
        </form>
    <?php } ?>
    <div class = "detail_view">
        <h4>번호: <?php echo $row['bid']; ?> 제목: <?php echo $row['title']; ?> 작성자: <?php echo $row['id']; ?></h4>
        <h6>작성일: <?php echo $row['created'];?> 조회수: <?php echo $row['hit'];?><h6>
        <h5><?php echo $row['detail'];?><h5>
    </div>
</body>
</html>
//read.js
function modify_board(){
    location.href='write.php?bid='+ document.getElementById('bid').value;
}

function remove_board(){
    location.href='remove.php?bid=' + document.getElementById('bid').value;
}
  • 여기서는 큰 문제는 없었지만, read.php에서 read.js에 있는 modify_board 함수를 못 읽는 문제가 있었다. modify_board 함수는 이전 이름은 modify였는데, 이름을 바꾸니 정상적으로 되었다. 아마도 버그거나, modify가 예약어중 하나라서 그런게 아닐까 예상하고 있다.

  • 다음은 게시글 작성에 관련된 코드를 올리겠다.(수정도 포함.)
//write.php
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Write</title>
</head>
<body>
    <?php
    session_start();
    if(isset($_SESSION['id'])){
        $id = $_SESSION['id'];
    }
    else{
        echo "<script>alert('Wrong path!');</script>";
        echo "<script>histroy.back();</script>";
        exit;
    }
    # 로그인 해야 접근 가능
    $title = '';
    $detail = '';
    $bid = $_GET['bid'];
//수정할 때만 if문 실행
    if(!empty($bid)){# modify
        $username = $_SESSION['id'];
        $mysqli = new mysqli('localhost', 'conn', 'Testnote!%89', 'test');
        $q = "SELECT * from board where bid = '$bid'";
        $row = ($mysqli->query($q))->fetch_array(MYSQLI_ASSOC);

        if($row['id'] != $username){
            echo "<script>alert('Wrong path!');</script>";
            echo "<script>location.replace('read_index.php')</script>";
            exit;
        }
        $title = $row['title'];
        $detail = $row['detail'];
    }
    ?>
    <form method="post" action="write_action.php" class = "writeForm" >
        <div>
            <input type="text" name = "title" style="width:600px" id = "title" class = "titleFrom" value = <?php echo $title; ?> >
        </div>
        <div>
            <input type="text" name = "detail" style="width:600px;height:400px" id = "detail" class = "detailForm" value = <?php echo $detail; ?> >
        </div>
        <div>
            <input type="hidden" name="bid" id = "bid" value = <?php echo $bid; ?> >
        </div>
            <button type="submit">작성</button>
            <button type="button" name = "cancel" id = "name" onclick="location.href='read_index.php'">취소</button>
    </form>
</body>
</html>
//write_action.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <?php
        session_start();
        if(!isset($_SESSION['id'])){
            echo "<script>alert('Wrong path!');</script>";
            echo "<script>history.back();</script>";
            exit;
        }
        $id = $_SESSION['id'];
        # 로그인을 해야만 접근 가능
        $mysqli = new mysqli('localhost', 'conn', 'Testnote!%89', 'test');//host, user, pw, db_name, you need to make table
        $bid = $_POST['bid'];
        $title = $_POST['title'];
        $detail = $_POST['detail'];
        if(!empty($bid)){# modify
            $q = "SELECT id from board where bid = $bid" # 전달 받은 bid 값이 올바른 값인지 확인
            $result = ($mysqli->query($q))->fetch_array(MYSQLI_ASSOC);
            if($result['id'] != $_SESSION['id']){
                echo "<script>alert('Wrong path!')</script>";
                echo "<script>location.replace('read_index.php');</script>";
                exit;
            }
            $q = "UPDATE board SET title = '$title', detail = '$detail' where bid = '$bid'";
            // modify할 때 query문
        }
        else{# write
            $q = "INSERT INTO board(id, title, detail, created) VALUES ('$id', '$title', '$detail', default)";
            // write할 때 query문
        }
        $result = $mysqli->query($q);
        if($result){
            echo "<script>alert('Your request is successfully posted!')</script>";
        }
        else{
            echo "<script>alert('Something is wrong with the server...')</script>";
        }
    ?>
</body>
</html>

  • 마지막으로 삭제와 관련된 코드를 올리겠다.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <?php
    session_start();
    if(!isset($_SESSION['id'])){
        echo "<script>alert('Wrong path!');</script>";
        echo "<script>history.back();</script>";
        exit;
    }
    $id = $_SESSION['id'];
    $bid = $_GET['bid'];
    $mysqli = new mysqli('localhost', 'conn', 'Testnote!%89', 'test');
    $q = "SELECT id from board where bid = '$bid'";
    $row = ($mysqli->query($q))->fetch_array(MYSQLI_ASSOC);

    if($row['id'] != $id){
        echo "<script>alert('Wrong path!');</script>";
        echo "<script>location.replace('read_index.php')</script>";
    }
    $q = "DELETE from board where bid = '$bid'";
    $row = $mysqli->query($q);

    if($row)
        echo "<script>alert('This Post was removed!');</script>";
        echo "<script>location.replace('read_index.php')</script>";
    else
        echo "<script>alert('Error! Something has been wrong!');</script>";
        echo "<script>location.replace('read_index.php')</script>";
    ?>
    
</body>
</html>
  • 로그인(로그인을 안했다면 수정, 작성, 삭제 못함)
  • bid 확인(수정하러 왔는지 작성하러 왔는지 확인 이후 수정할 게시글 확인/
    remove의 경우 삭제할 게시글 확인)
  • 확인한 bid로 DB에서 id를 가져와 session의 id와 비교
    (로그인했다고 다른 사람의 게시글을 수정하면 안 되니.)
  • 이 순서대로 write.php, write_action.php, remove.php 셋 다 검증을 한다.

느낀점과 고칠점

  • 개인적으로 이번 웹개발을 하면서 조금 힘들었다. 생각할 점도 많았고, 추가해야할 기능도 많았기 때문이다.
  • 그래도 시간 안에 생각했던 것만큼의 결과가 나와서 다행이라고 생각한다.
  • 고쳐야할 점이 있다면 스켈레톤 UI 되시겠다. CSS까지 볼 시간이 없긴한데 간단하게라도 만져봐야할 것 같다.

앞으로 할 일

  • XSS 취약점 확인
  • 게시글 페이징 (번호)
profile
오늘 공부한 것을 올리는 공간 / 일주일에 글 3개 / 블로그 이전 : https://perorochan321.tistory.com/
post-custom-banner

0개의 댓글