본문 바로가기
WEB HACKING/웹 해킹[실습]

Php로 웹 개발하기 : 문의 게시판(1)

by madevth 2021. 12. 15.
반응형

이번 웹 개발에서 마지막으로 구현할 페이지는 비회원도 사용할 수 있는 문의 게시판이다.

기존에 만들었던 일반 게시판과 거의 유사하지만, 비회원도 문의글을 작성하고 비밀번호를 통해 글을 조회할 수 있다는 점만 차이가 있다.

 

문의 게시판의 형태는 게시판과 똑같이 만들 것이고, 회원이 글을 쓰면 자신의 비밀번호로 설정되고 비회원이 글을 쓰면 따로 비밀번호를 입력받도록 만들 것이다.

우선 qna 테이블을 만들어주자.

mysql> CREATE TABLE qna (
    -> `id` int(5) AUTO_INCREMENT PRIMARY KEY,
    -> `title` varchar(20),
    -> `content` varchar(5000),
    -> `password` varchar(20) NOT NULL
    -> );

[qna.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">
    <link href="./css/style.css"  rel = "stylesheet"/>
    <title>Q&A</title>
</head>
<body>
    <div class = "column">
        <form action = "qna_create.php" method = "post" enctype="multipart/form-data">
            <div class = "posting">
                <input class = "posting_title" name = "create_title" type = "text" placeholder = "제목"/>
                <textarea class = "posting_contents" name = "create_body" placeholder = "내용"></textarea>
                <input class = "writeBtn" type = "submit" value = "create">
            </div>
        </form>
    </div>
</body>
</html>

[qna_create.php]

<?php
    if(isset($_POST['create_title']) && isset($_POST['create_body']) && isset($_POST['create_title']) != NULL && isset($_POST['create_body']) != NULL){
        $conn = mysqli_connect('localhost', 'ID', 'PW', 'DBname');
        session_start();
        $title = mysqli_real_escape_string($conn, $_POST['create_title']);
        $content = mysqli_real_escape_string($conn, $_POST['create_body']);

        if(isset($_SESSION['id'])) $username = $_SESSION['id'];
        else $username = "";
        $sql = "SELECT login_pw FROM login where login_id = '$username';";
        
        if($result = mysqli_fetch_array(mysqli_query($conn, $sql))){
            $password = $result[0];
        }else{
            echo "<script>var password = prompt('비밀번호를 입력해주세요.', '비밀번호');</script>";
            $password = "<script>document.write(password);</script>";
        }
        
        $sql2 = "INSERT INTO qna (title, content, password) VALUES ('$title', '$content', '$password');";
        if($result2 = mysqli_query($conn, $sql2)){
            echo "<script>alert('글 작성에 성공하셨습니다!')</script>";
            echo "<script>window.location.href='qna.php';</script>";
        } else{
            echo mysqli_error($conn);
        }
        mysqli_close($conn);
    }
?>

test 계정으로 로그인해서 문의글을 남겨보자.

잘 저장되었다.

 

이번에는 비회원으로 글을 남겨보자.

비회원으로 글을 작성하니 비밀번호 받는 창이 잘 떴다.

그런데 Data too long for column 'password' at row 1 에러가 떴다.

테이블에서 설정한 varchar(20) 보다 짧은 패스워드를 넣어도, test 계정과 같은 12345를 넣어도 같은 에러가 떴다.

그런데 MySQL에 직접 insert 하면 문제없이 잘 들어갔다.

그래서 <script> 태그를 섞어서 써서 비밀번호 말고 다른 문자열이 추가로 들어가나? 싶어서 echo $password;를 해주니 비밀번호만 잘 떴다.

 

찾아보니 Data too long for column 에러는 varchar의 크기를 늘려주거나, 모드를 바꾸는 해결책이 있었다. 

MySQL에서 잘 들어가니 위의 문제는 아닌 것 같았지만 우선 모드를 바꿔주었다. (STRICT_TRANS_TABLES 삭제)

다시 문의글을 작성해보았다.

??! echo 했을 때는 분명히 입력한 password만 나왔는데 테이블에는 스크립트 태그까지 들어가고 있었다.

모드를 다시 원상태로 복구시킨 후 sql 구문을 출력해보았다.

분명히 여기서는 비밀번호만 잘 들어가는데..

알아보니 자바스크립트와 php가 서로 다른 타이밍에 실행되기 때문에 그런 것 같다.

php가 먼저 실행되고 javascript가 실행되므로 우리한테는 javascript가 실행된 값이 보이지만, MySQL 서버에는 php만 실행된 값이 바로 넘어가는 것이다.

 

그 증거로 password의 사이즈를 늘린 후 MySQL에 들어가는 값을 보면

위와 같이 문자열 password로 들어가 있는 것을 볼 수 있다. password 값을 받기 전에 MySQL 서버에 저장된 것이다.

 

로직이 잘못되었기 때문에 새롭게 구상하였다.

[qna.php]

<?php
    session_start();
    if(isset($_SESSION['id'])) {
        $flag = 0;
    } else{
        $flag = 1;
    }
?>
<script>
    function get_pw(){
        var flag = <?php echo $flag ?>;
        if(flag){
            document.getElementById('password').value = prompt('비밀번호를 입력해주세요.', '비밀번호');
        }
    }
</script>
<div class = "column">
    <form action = "qna_create.php" method = "post" enctype="multipart/form-data">
        <div class = "posting">
            <input class = "posting_title" name = "create_title" type = "text" placeholder = "제목"/>
            <textarea class = "posting_contents" name = "create_body" placeholder = "내용"></textarea>
            <input name = "password" id = "password" type = "hidden"/>
            <input class = "writeBtn" type = "submit" value = "create" onClick="get_pw()">
        </div>
    </form>
</div>

mypage의 로직과 비슷하게 password를 hidden으로 넣어주고 onClick으로 그 값을 조정한다.

단, 미리 세션을 검증하여 아이디가 없는 경우에만 prompt를 실행해준다.

 

qna_create.php에서는 아이디가 없는 경우의 패스워드를 $_POST ['password'] 값으로 설정해준다.

if($result = mysqli_fetch_array(mysqli_query($conn, $sql))){
    $password = $result[0];
}else{
    $password = $_POST['password'];
}

prompt 창도 잘 뜨고 저장도 잘 되는 것을 확인할 수 있다.

반응형

댓글