본문 바로가기

개발과제/보안추가

[노말틱 모의 해킹 취업반 추가 개발과제 ] PreparedStatement 적용하기 -1

제가 만든 PHP문에서 SQL문을 보안이 더욱 강력한 PreparedStatement 방식으로 전부 바꾸겠습니다.

다하면 너무 길거 같으니 나누어서 올리겠습니다.

 

PreparedStatement란?

영어 단어를 그대로 보시면 준비된 문장입니다.

SQL 쿼리 문장을 미리 준비한 후, 데이터베이스에 전달하여 실행하는 방식입니다!

 

장점으로 보안성이 좋아지고 성능이 향상되고 코드의 가독성이 좋아집니다.

 

즉 먼저 SQL문장을 준비하고 그 뒤에 오는 문자들은 전부 문자로 처리하는 겁니다.

.

.

.

그래서 안 쓸 이유가 없죠!

저도 쓰겠습니다.

 

조금 많지만..

 

힘내볼게요! 시간이 남으면 각 기능별로 폴더 나누어서 분류를 하겠습니다.

 

 

 

적용하는 것은 간단해요 escape 함수를  전부 지우고 preparedstatement 적용하면 됩니다.

제가 쓸 sql문을 작성하고 그리고 외부 입력으로 들어갈 곳을 ? 로 대체 합니다.

 

그리고 prepare을 이용하여 미리 쿼리문을 실행합니다.

 

또한 ?로 들어갈 파라미터들이 어떻게 들어갈지까지 정하면 좋습니다.

 

https://je0n-je.tistory.com/103

 

저는 이 블로그에서 참고했습니다!

 

간단하게 순서을 설명드릴게요

 

1. preparedStatement 초기화한다, SQL문 작성

2. preraedStatement 적용한다. ex) $stmt = mysqli_prepare();

3. 바인딩한다 mysqli_stmt_bind_param() 함수 사용

4. 실행한다 mysqli_stmt_execute() 사용

5. 결괏값이 필요하면 mysqli_stmt_get_result 함수 사용한다

6. 마지막에 종료시킨다

 

 

.

.

.

.

 

-board.php

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Welcome!</title>
    </head>
    <body>
        <h1>MENU</h1>
        <?php

            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$db_board);

            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }
        ?>

        <form method ="GET" action="board.php">
            <input type = "text" name="search" value="<?php echo filter_var(strip_tags($_GET['search']),FILTER_SANITIZE_SPECIAL_CHARS);?>" placeholder="검색" >
            <input type="submit" value="검색">
            <select name="sort" onchange="this.form.submit()">
                <option value="">정렬 방식 선택</option>
                <option value="date" <?php if(filter_var(strip_tags($_GET['sort']),FILTER_SANITIZE_SPECIAL_CHARS)=='date'){echo ' selected';} ?> >날짜순</option>
                <option value="likes" <?php if(filter_var(strip_tags($_GET['sort']),FILTER_SANITIZE_SPECIAL_CHARS)=='likes'){echo ' selected';} ?> >추천순</option>
                <option value="author" <?php if(filter_var(strip_tags($_GET['sort']),FILTER_SANITIZE_SPECIAL_CHARS)=='author'){echo ' selected';} ?> >작성자순</option>
            </select>          
            <label for="date">날짜 선택:</label>
            <input type="date" id="date_value" name="date_value" value="<?php echo isset($_GET['date_value']) ? $_GET['date_value'] : ''; ?>">
        </form>

        <p>
        <?php 
            //한 페이지에 보여줄 게시물 수
            $num_per_page = 5;

            //현재 페이지 번호
            if(isset($_GET['page'])) {
                $page = mysqli_real_escape_string($conn,filter_var(strip_tags(intval($_GET['page'])),FILTER_SANITIZE_SPECIAL_CHARS));
            } else {
                $page = 1;
            }
            
            //검색이 입력된 경우
            if(isset($_GET['search'])) {
                $search = filter_var(strip_tags($_GET['search']),FILTER_SANITIZE_SPECIAL_CHARS);
                
                if(isset($_GET['date_value']) && strtotime($_GET['date_value'])) {
                    //날짜 선택한 경우, strtotime() 이용해 유효한 값인지 확인
                    $date_value = filter_var(strip_tags($_GET['date_value']),FILTER_SANITIZE_SPECIAL_CHARS);
                    $date_value = DateTime::createFromFormat('Y-m-d', $date_value)->format('Y-m-d'); //날짜 값으로 다시 바꾼다
                }
                else {
                    //날짜가 선택이 안된 경우
                    $date_value = '';
                }
            } else {
                //검색이 입력되지 않은 경우
                $search = '';
                $date_value = '';
            }
            //각 %을 붙여서 포함 된 문자열을 찾을 수 있게 한다
            $search_value = '%'.$search.'%';
            $date_value_value = '%'.$date_value.'%';


            $sql = "SELECT board_id,id,title,detail,views,like_value FROM $db_board WHERE title LIKE ? AND date_value LIKE ? ";
            $total_sql = "SELECT count(*) AS cnt FROM $db_board WHERE title LIKE ? AND date_value LIKE ? ";

            $stmt2 = mysqli_stmt_init($conn); //preparedstatement 초기화 

            //total_sql문 preparedStatement 적용
            $stmt2 = mysqli_prepare($conn, $total_sql);
            mysqli_stmt_bind_param($stmt2, 'ss', $search_value , $date_value_value); //s는 string, i는 정수형을 뜻한다
            mysqli_stmt_execute($stmt2); //실행
            $total_result = mysqli_stmt_get_result($stmt2); //결과
            $total_row = mysqli_fetch_assoc($total_result); //결과를 배열로 가져온다
            $total_posts = $total_row['cnt']; //배열 중 cnt의 값을 가져온다

            //전체 페이지 수
            $total_pages = ceil($total_posts / $num_per_page);

            //각 페이지 시작 인덱스
            $start = ($page - 1) * $num_per_page;

            //정렬해주는 조건문
            if (isset($_GET['sort'])) {
                $sort = filter_var(strip_tags($_GET['sort']),FILTER_SANITIZE_SPECIAL_CHARS);
                if ($sort == 'date') {
                    //날짜순
                    $sql .= " ORDER BY date_value DESC";
                } else if ($sort == 'likes') {
                    //추천순
                    $sql .= " ORDER BY like_value DESC";
                } else if ($sort == 'author') {
                    //작성자순
                    $sql .= " ORDER BY id DESC";
                }
            } 
            
            $sql .= " LIMIT $start, $num_per_page "; //최대 5개씩 호출

            $stmt = mysqli_stmt_init($conn); //preparedstatement 초기화 

            //쿼리문 실행 preparedstatement 적용
            $stmt = mysqli_prepare($conn,$sql);
            mysqli_stmt_bind_param($stmt, 'ss',  $search_value , $date_value_value); //s는 string, i는 정수형을 뜻한다
            mysqli_stmt_execute($stmt);
            $result = mysqli_stmt_get_result($stmt);

            if(mysqli_num_rows($result) > 0) {
                //게시물 출력
                while($row = mysqli_fetch_assoc($result)) {
                    $index = $row['board_id'];
                    $id = $row['id'];
                    $title = $row['title'];
                    $like_value = $row['like_value'];
                    echo '<p><a href="view_board.php?index='.$index.'">'.$title.'</a> : '.$id.'작성함 조회수: '.$row['views'].' 좋아요 수: '.$like_value.'</p>';
                }
            } else {
                echo "게시물이 없습니다!";
            }
            
            echo '<p> [ ';
            
            // 현재 페이지를 10으로 나눈 몫에 10을 곱한 값에서 1을 빼면
            // 현재 페이지가 몇 번째 페이지 블록에 있는지 알 수 있습니다.
            $block_start = floor(($page-1)/10)*10;

            if ($block_start > 1) {
                // 이전 페이지 블록이 있다면, 다음 버튼을 출력합니다.
                $next_block_start = $block_start - 10;
                if($next_block_start == 0) {
                    $next_block_start += 1; //0페이지는 존재 하지 않기에 1더한다
                }
                echo '<a href="?page=' . $next_block_start .'"><< </a>';
            }

            // 이전 버튼 출력
            if ($page > 1) {
                echo '<a href="?page=' . ($page-1) .'">< </a> ';
            }
            
            // 페이지 링크 출력
            for ($i = $block_start+1; $i <= min($block_start+10, $total_pages); $i++) {
                if($i == $page) {
                    echo '<strong>'.$i.' </strong>';
                } else {
                    echo '<a href="?page=' . $i .'">'.$i. '</a> ';
                }
                echo ' ';
            }

            // 다음 버튼 출력
            if ($page < $total_pages) {
                echo '<a href="?page=' . ($page+1) .'">> </a> ';
            }
            
            if ($block_start+10 < $total_pages) {
                // 다음 페이지 블록이 있다면, 다음 버튼을 출력합니다.
                $next_block_start = $block_start + 11;
                echo '<a href="?page=' . $next_block_start .'">>></a>';
            }

            echo ' ]</p>';

            mysqli_stmt_close($stmt); //preparedstatement 종료
            mysqli_stmt_close($stmt2);
            
        ?>
        </p>
        <p></p>
        <form action="write_board.php" method="POST"> 
            <p><input type="submit" name="write" value="게시판 작성"></p>
        </form>
        <form action="only_login.php"> 
            <p><input type="submit" value="메인페이지로"></p>
        </form>
        <form action="board.php" method="GET"> 
            <p><input type="submit" value="검색 초기화"></p>
            <input type="hidden" name="search" value="">
            <input type="hidden" name="sort" value="">
            <input type="hidden" name="date_value" value="">
        </form>
    </body>
</html>

 

생각보다 오래 걸리네요!

수정하는데만 1시간 걸렸습니다.. 한 번 할 수 있는 데까지 해보겠습니다.

 

 

-change_id.php

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Welcome! HACKER!</title>
    </head>
    <body>
        <h1>MY PAGE!</h1>
        <p>
        <?php 
            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$dbname); //로그인
            $conn_for_board = mysqli_connect($host,$username,$password,$db_board); //게시판

   
            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }        
        ?>
        </p>
        <form action="change_id.php" method="GET"> 
            <p><input type="text" name="old_id" placeholder="기존 ID입력" required></p>
            <p><input type="text" name="new_id" placeholder="변경할 ID,특수기호는 입력X" required></p>
            <p><input type="submit" value="수정하기"></p>
        </form>
        
        <p></p>
        <form action="only_login.php">
            <p><input type="submit" value="메인으로 돌아가기"></p>
        </form>
        
        <?php
            if(isset($_GET['new_id']) && isset($_GET['old_id'])) {
                //보안 검사
                $old_id = filter_var(strip_tags($_GET['old_id']),FILTER_SANITIZE_SPECIAL_CHARS);
                $new_id = filter_var(strip_tags($_GET['new_id']),FILTER_SANITIZE_SPECIAL_CHARS);

                if($_SESSION['login_id'] == $old_id) {
                    //ID 변경, 게시물도 전부 id 수정
                    $sql = "UPDATE LOGIN_INFO SET id= ? WHERE id = ? ";
                    $sql_board = "UPDATE BOARD_INFO SET id=? WHERE id = ?";

                    //세션 할당
                    $_SESSION['login_id'] = $new_id;


                    //preparedStatement 적용
                    $stmt = mysqli_prepare($conn, $sql);
                    $stmt_board = mysqli_prepare($conn_for_board,$sql_board);

                    //바인딩
                    mysqli_stmt_bind_param($stmt,'ss',$new_id, $old_id);
                    mysqli_stmt_bind_param($stmt_board,'ss',$new_id,$old_id);

                    //sql 실행
                    if(mysqli_stmt_execute($stmt)) {
                        $_SESSION['write_error'] = "ID가 수정 됬습니다!";
                    } else {
                        //실패시
                        $_SESSION['write_error'] = '작성 중 오류가 발생하였습니다.';
                    }

                    //게시판sql 실행
                    if(mysqli_stmt_execute($stmt_board)) {
                        $_SESSION['write_error'] = "ID가 수정 됬습니다!";
                    } else {
                        //실패시
                        $_SESSION['write_error'] = '작성 중 오류가 발생하였습니다.';
                    }
                    
                    //prepared statement 종료
                    mysqli_stmt_close($stmt);
                    mysqli_stmt_close($stmt_board);

                    //전 페이지로 이동
                    header("Location: my_info.php");
                    exit();

                } else {
                    $_SESSION['write_error'] = 'ID가 틀립니다!';
                }
            }
        ?>
        <p></p>
        <?php 
                if (isset($_SESSION['write_error'])) {
                    echo $_SESSION['write_error'];
                    unset($_SESSION['write_error']);
                }
        ?>
    </body>
</html>

 

 

 

-change_pw

딱히 바꿀 이유가 없네요! 비밀번호는 해싱이라 sql문을 조작을 못합니다

 

 

-delete_board.php

<?php
    include 'DB_INFO.php'; //데이터 베이스 정보

    session_start(); //세션 시작
    
    if(!isset($_SESSION['login_id'])) {
        //로그인하지 않은 사용자
        header("Location: login.php"); //login 화면으로 바꾼다
        exit(); //이 페이지를 바로 닫는다
    }
    
    //게시판 데이터베이스 연결
    $conn = mysqli_connect($host,$username,$password, $db_board);
    
    //데이터베이스 오류시 종료
    if(mysqli_connect_errno()) {
        die("데이터 베이스 오류: ". mysqli_connect_error());
    }

    //POST로 전달된 정보 받기
    $board_id = filter_var(strip_tags($_POST['board_id']),FILTER_SANITIZE_SPECIAL_CHARS);

    //session으로 유저 이름 받기
    $user_id = $_SESSION['login_id'];
    
    //삭제용 sql문 작성
    $sql = "DELETE FROM $db_board WHERE board_id= ? ";

    //preparedStatement 적용
    $stmt = mysqli_prepare($conn, $sql);
    
    //바인딩
    mysqli_stmt_bind_param($stmt,'s', $board_id );

    //실행
    if(mysqli_stmt_execute($stmt)) {
        //실행 후 게시판으로 이동
        header("Location: board.php");
    } else {
        //오류 발생 시 메시지 호출
        $_SESSION['write_error'] = '삭제하는데 실패했습니다! 조금 있다 하십시오';
        header("Location: view_board.php");
    }
    //prepared 종료
    mysqli_stmt_close($stmt);

    exit();
?>

 

 

 

-download_process.php

딱히 수정할 게 없지만 filename에 basename 함수를 추가하여 파일 경로를 안 보이게 하겠습니다

 

<?php
    if(isset($_GET['filename'])) {
        // 파일 이름 및 경로 가져오기
        $filename = basename(filter_var(strip_tags($_GET['filename']),FILTER_SANITIZE_SPECIAL_CHARS));
        $filepath = '/path/to/upload/directory/'.$filename;
    
        // 파일이 존재하는지 확인
        if(file_exists($filepath)) {
            // 다운로드 헤더 설정
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($filepath));
            readfile($filepath);
            exit;
        } else {
            echo '파일이 존재하지 않습니다.';
        }
    } else {
        echo '파일 이름이 전달되지 않았습니다.';
    }
?>

 

 

 

 

-fix_board.php

 

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>게시판 수정 중</title>
    </head>
    <body>

        <?php 
            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$db_board);

            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }
            
            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }
            //GET방식으로 board_id 받기
            $board_id = filter_var(strip_tags($_GET['board_id']),FILTER_SANITIZE_SPECIAL_CHARS);

            //작성된 게시물들 조회 문
            $sql = "SELECT * FROM $db_board WHERE board_id = ? ";

            //preparedStatement 적용
            $stmt = mysqli_prepare($conn, $sql);
    
            //바인딩
            mysqli_stmt_bind_param($stmt,'s', $board_id );
            
            //실행
            mysqli_stmt_execute($stmt);

            //실행 결과 가져오기
            $result = mysqli_stmt_get_result($stmt);

            //결과값 가져오기
            $row = mysqli_fetch_assoc($result);
        ?>
        <form action="write_process_board.php" method="POST" enctype="multipart/form-data"> 
            <p><input type="text" name="title" maxlength="44" value="<?php echo $row['title']; ?>" placeholder="제목 입력, 최대 44자까지 가능합니다"></p>
            <p><textarea name="detail" rows="20" cols="20" maxlength="254" placeholder="내용 작성,최대 254자 가능합니다"><?php echo $row['detail']; ?></textarea></p>
            <p><input type="file" name="file" id="fileToUpload"></p>
            <?php
                if (isset($row['file_name'])) {
                    $file_name = implode('_', array_slice(explode('_', $row['file_name']), 1)); // '_' 문자를 기준으로 분리 후 첫 번째 요소를 제외한 나머지 요소를 모두 합쳐서 파일명을 구성합니다.
                    echo '<p>FILE: '.$file_name.'</p>';
                }
            ?>
            <p><input type="submit" value="수정하기"></p>
            <input type="hidden" name='board_id' value="<?php echo $row['board_id']; ?>">
        </form>

        <p>
        <?php session_start();
                if (isset($_SESSION['write_error'])) {
                    echo $_SESSION['write_error'];
                    unset($_SESSION['write_error']);
                }
                
                //prepared 종료
                mysqli_stmt_close($stmt);
        ?>
        </p>
    </body>
</html>

 

 

-write_board.php

딱히 없네요 패스

 

 

 

-write_process_board.php

 

<?php
    include 'DB_INFO.php'; //데이터 베이스 정보

    session_start(); //세션 시작

    if(!isset($_SESSION['login_id'])) {
        //로그인하지 않은 사용자
        header("Location: login.php"); //login 화면으로 바꾼다
        exit(); //이 페이지를 바로 닫는다
    }

    //게시판 데이터베이스 연결
    $conn = mysqli_connect($host,$username,$password, $db_board);

    //데이터베이스 오류시 종료
    if(mysqli_connect_errno()) {
        die("데이터 베이스 오류: ". mysqli_connect_error());
    }

    //POST로 전달된 정보 받기
    if(isset($_POST['board_id'])){
        $board_id = filter_var(strip_tags($_POST['board_id']),FILTER_SANITIZE_SPECIAL_CHARS);
    } else {
        $board_id = null;
    }
    $title = filter_var(strip_tags($_POST['title']),FILTER_SANITIZE_SPECIAL_CHARS);
    $detail = filter_var(strip_tags($_POST['detail']),FILTER_SANITIZE_SPECIAL_CHARS);

    if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_FILES['file'])) {
        // 업로드된 파일 정보 가져오기
        $file_name = $_FILES['file']['name'];
        $timestamp = time(); // 현재 시간을 초로 반환
        $new_file_name = $timestamp . '_' . $file_name; // 현재 시간과 원래 파일 이름을 합쳐 새로운 파일 이름 생성
        $file_tmp_name = $_FILES['file']['tmp_name'];
        $file_size = $_FILES['file']['size'];
        $file_error = $_FILES['file']['error'];
        $allowed_mime_types = ['image/jpeg', 'image/png', 'image/gif','text/plain','application/zip','application/x-hwp','application/msword','application/vnd.ms-excel','application/pdf']; //MIME 허락 된 것
        //확장자 허락 된 것
        $allowed_extensions = array("jpg","png","gif","txt","zip","hwp","word","xls","xlsx","pdf");

        //sql공격 방지용
        $new_file_name = mysqli_real_escape_string($conn,$new_file_name);

        // 파일 업로드가 정상적으로 처리되었는지 확인
        if ($file_error === UPLOAD_ERR_OK) {
            // 파일 MIME 타입 확인, 조작됬는지 확인
            $file_mime_type = mime_content_type($file_tmp_name);
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $file_mime_type = finfo_file($finfo, $file_tmp_name);
            finfo_close($finfo);
            
            if (in_array($file_mime_type, $allowed_mime_types)) {

                //파일 확장자 확인
                $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
                if(in_array($file_ext, $allowed_extensions)) {
                // 파일 저장 경로
                $upload_path = '/path/to/upload/directory/' . $new_file_name;

                    // 파일 이동 및 저장
                    if (move_uploaded_file($file_tmp_name, $upload_path)) {
                        $_SESSION['file_error'] =  '파일 업로드 성공';
                    } else {
                        $_SESSION['file_error'] =  '파일 업로드 실패';
                    }
                } else {
                    $_SESSION['file_error'] =  '잘못된 파일 형식입니다';
                }
            } else {
                $_SESSION['file_error'] =  '잘못된 파일 형식입니다';
            }
        }
    }
    //session으로 유저 이름 받기
    $user_id = $_SESSION['login_id'];

    if(isset($board_id)) {
        //board_id가 있다는 것은 수정을 의미
        $sql = "UPDATE $db_board SET title = ?, detail= ?, file_name= ? WHERE board_id= ? ";
        //preparedstatement 적용
        $stmt = mysqli_prepare($conn, $sql);
        mysqli_stmt_bind_param($stmt, 'sssi', $title, $detail, $new_file_name, $board_id);
    }
    else {
        //board_id가 없으니 새로 만드는 sql문
        $sql = "INSERT INTO $db_board (id, title, detail,file_name) VALUES (?, ?, ?,?)";
        $stmt = mysqli_prepare($conn, $sql);
        mysqli_stmt_bind_param($stmt, 'ssss', $user_id ,$title, $detail, $new_file_name);
    }

    //sql문 실행
    if(mysqli_stmt_execute($stmt)) {
        //수정인 경우 바로 게시판 보이게 함
        if(isset($board_id)) {
            $_SESSION['write_error'] = '수정되었습니다!';
            header("Location: view_board.php?index=$board_id");
        }
        else {
            $board_id = mysqli_insert_id($conn); // 새로 생성한 게시물의 id를 가져옴
            $_SESSION['write_error'] = '작성되었습니다!';
            header("Location: view_board.php?index=$board_id");
        }
    } else {
        $_SESSION['write_error'] = '작성 중 오류가 발생하였습니다.';
        header("Location: view_board.php");
    }

    mysqli_stmt_close($stmt);

    exit();
?>

 

 

 

-view_board.php

 

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>게시물 보는중</title>
    </head>
    <body>
        <p>
        <?php 

            include 'DB_INFO.php'; //데이터 베이스 정보

            //데이터베이스 연결
            $conn = mysqli_connect($host,$username,$password,$db_board);

            //데이터베이스 오류시 종료
            if(mysqli_connect_errno()) {
                die("데이터 베이스 오류: ". mysqli_connect_error());
            }

            session_start(); //세션 시작

            if(!isset($_SESSION['login_id'])) {
                //로그인하지 않은 사용자
                header("Location: login.php"); //login 화면으로 바꾼다
                exit(); //이 페이지를 바로 닫는다
            }

            //GET방식으로 전달된 index 받는다
            $board_id = filter_var(strip_tags($_GET['index']),FILTER_SANITIZE_SPECIAL_CHARS);
            //가독성 위해 다른 변수에 저장
            $last_viewed_time_for_board_id = 'last_view_time_'.$board_id;

            // 세션에 마지막 조회 시간 정보가 있는지 확인
            if (!isset($_SESSION[$last_viewed_time_for_board_id])) {
                // 세션에 마지막 조회 시간 정보가 없으면 현재 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = time();
            } else {
                // 세션에 마지막 조회 시간 정보가 있으면 일정 시간이 지났는지 확인
                $last_view_time = $_SESSION[$last_viewed_time_for_board_id];
                $current_time = time();
                $time_diff = $current_time - $last_view_time;
                if ($time_diff >= 60) { // 60초(1시간) 이상 지났으면 조회수 증가
                //조회수 증가하는 sql문
                $sql_view = "UPDATE $db_board SET views = views + 1 WHERE board_id = ? ";

                //prepared 적용
                $stmt = mysqli_prepare($conn, $sql_view);
                //바인딩
                mysqli_stmt_bind_param($stmt, 'i' , $board_id);
                //실행
                mysqli_stmt_execute($stmt);

                // 세션에 현재 조회 시간을 저장
                $_SESSION[$last_viewed_time_for_board_id] = $current_time;
                }
            }

            //작성된 게시물들 조회 문
            $sql = "SELECT * FROM $db_board WHERE board_id = ? ";
            //prepared 적용
            $stmt = mysqli_prepare($conn, $sql);
            //바인딩
            mysqli_stmt_bind_param($stmt, 'i' , $board_id);
            //실행
            mysqli_stmt_execute($stmt);
            //결과값 받기
            $result = mysqli_stmt_get_result($stmt);
            
            //게시물 출력
            while($row = mysqli_fetch_assoc($result)) {
                echo '<p>조회수: '.$row['views'].'</p>';
                echo '<p>좋아요: '.$row['like_value'].'</p>';
                echo '<p>ID: '.$row['id'].'</p>';
                echo '<p>Title: '.$row['title'].'</p>';
                echo '<p>Detail: '.$row['detail'].'</p>';
                echo '<p>Date: '.$row['date_value'].'</p>';
                if (isset($row['file_name'])) {
                    $file_name = implode('_', array_slice(explode('_', $row['file_name']), 1)); // '_' 문자를 기준으로 분리 후 첫 번째 요소를 제외한 나머지 요소를 모두 합쳐서 파일명을 구성합니다.
                    $download_url = 'download_process.php?filename='.$row['file_name'];
                    echo '<p>FILE: <a href="'.$download_url.'">'.$file_name.'</a></p>';
                }
                
                //로그인한 사용자의 정보 가져온다
                $user_id = $_SESSION['login_id'];

                //게시물 작성자와 로그인한 ID와 일치한 경우
                if($row['id'] == $user_id) {
                    //게시물 수정 버튼을 보여준다
                    echo "<form method='GET' action='fix_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>게시물 수정</button></p>
                          </form>";

                    //게시물 삭제 버튼을 보여준다
                    echo "<form method='POST' action='delete_board.php'>
                            <input type='hidden' name='board_id' value='".$row['board_id']."'>
                            <p><button type='submit'>삭제</button></p>
                          </form>";
                }
                
                //게시물 좋아요 버튼을 보여준다
                echo "<form method='POST' action='like.php'>
                        <input type='hidden' name='board_id' value='".$row['board_id']."'>
                        <p><button type='submit'>좋아요!</button></p>
                    </form>";

            }


            mysqli_stmt_close($stmt);
        ?>
        </p>
        <p>
        <?php session_start();
                if (isset($_SESSION['write_error'])) {
                    echo $_SESSION['write_error'];
                    unset($_SESSION['write_error']);
                }
        ?>
        </p>
        <p>
        <?php session_start();
                if (isset($_SESSION['file_error'])) {
                    echo $_SESSION['file_error'];
                    unset($_SESSION['file_error']);
                }
        ?>
        </p>
        <p></p>

        <form action="write_board.php" method="POST"> 
            <p><input type="submit" name="write" value="게시판 작성"></p>
        </form>
        <form action="board.php">
            <p><input type="submit" value="메인페이지로"></p>
        </form>
    </body>
</html>

 

여기까지 작성하고 내일 마저 수정하겠습니다!

 

너무 길어지네요 나머지는 대부분 페이지이고 게시판이라 저희가 방금 수정한 것처럼 복사 붙이기 하면 될 것 같아요!