본문 바로가기

웹 개발

[14주차] 문의 게시판 구현 #2 - 비밀번호 인증

벌써 웹 개발의 마지막 포스팅이다

 

마지막으로 구현해볼 것은 비회원도 이용할 수 있는 문의 게시판이다

 

비회원도 이용할 수 있기 때문에 비밀번호로 게시글을 잠금할 수 있는 기능을 만들어볼 것이다

 

qna_write.php

<?php
//비회원도 이용가능해야하므로 세션없어도 이용가능해야함
session_start();
?>
<!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>문의 게시판 글쓰기</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    <?php
require('./nav.html');
?>
<style>
#boardwrite{
    margin:0 auto;
}

</style>


</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
        <BR>
        <h1>문의 게시판 글쓰기</h1>
        <HR>
            <form action="./qna_write_proc.php" method="POST" enctype="multipart/form-data">
                <table id="boardwrite">
                    <thead>
                        <tr>
                            <th>제목</th>
                            <td class="title"><input style="width:700px;" type="text" name="bTitle" id="bTitle"></td>
                        </tr>
                        <tr>
                            <th>내용</th>
                            <td class="content"><textarea style="width:700px;height:400px;" name="bContent" id="bContent"></textarea></td>
                        </tr>
                        <tr>
                            <th>전화번호</th>
                            <td class="phone"><input placeholder="비밀글로 하시려면 작성해주세요" style="width:700px;" type="text" name="bPhone" id="bPhone"></td>
                        </tr>
                        <tr>
                            <th></th>
                            <td>
                                <!-- 게시글 잠금 기능 -->
                        <input type="checkbox" value="1" name="lockpost" id="lockpost"/> 비밀글 설정
                        </td>
                        </tr>    
                        </thead>
                        <tbody>
                        <tr>
                            <th></th>
                            <td>
                                <input type="file" name="board_file" />
                            <a href="qna_board.php" class="btnLIst btn"><div style="margin-left:300px;border:2px solid grey;">목록</div></a> 
                            <button 
                            style="background-color:pink" 
                            type="submit" 
                            onClick=
                            "return confirm('이대로 작성하시겠습니까? \n전화번호를 남기셨으면 차후 전화번호인증을 통해 게시글을 열람할 수 있습니다.')">
                            <div class="btnSEt">작성</div>
                            </button>
                        </td>
                        </tr>
                    
                    </tbody>
                </form> 
</body>
</html>

 

자유 게시판과의 차이점은 전화번호를 넣는 칸이 생겼고 비밀글 설정 버튼이 추가되었다는 점이다

 

이 전화번호를 통해 비밀글을 열람할 수 있다

비밀글 설정 체크박스를 체크하면 lock_post라는 문의 게시판db 컬럼에 저장한다

 

$lockpost는 잠겼을 때 1, 열렸을 때 0이다

 

작성 버튼을 누르면 작성한 값을 qna_write_proc.php로 전송한다

 

qna_write_proc.php

<?php
//세션 시작
session_start();

//작성된 값을 받아서 변수로 저장함
if(isset($_SESSION['id'])){
    $name = $_SESSION['id'];
} else {
    $name = "익명";
}


$bPhone = $_POST['bPhone'];
$bTitle = $_POST['bTitle'];
// $bNick = $_POST['bNick'];
echo $_POST['lockpost'];
$date = date('Y-m-d');
$bContent = $_POST['bContent'];

if(isset($_POST['lockpost'])){
    $lock_post = 1 ;
} else {
    $lock_post = 0 ;
}

//파일 관련 변수
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_FILES['board_file'])){
// $filesize=$_FILES['board_file']['size'];
// $file_error=$_FILES['board_file']['error'];
$tmpfile = $_FILES['board_file']['tmp_name'];
$origin_filename = $_FILES['board_file']['name'];
$allowed_mime_types =['image/jpeg','image/png','image/gif','application/zip','application/x-hwp','application/msword','application/pdf']; //mime허락된 형식
$filename = iconv("UTF-8","EUC-KR",$_FILES['board_file']['name']);

$timestamp = time();
$new_filename = $timestamp.'_'.$filename;
$file_mime_type = mime_content_type($tmpfile);
// if(in_array($file_mime_type, $allowed_mime_types)){
    //파일 저장 경로
    $upload_path = './upload/'.$new_filename;
    if(move_uploaded_file($tmpfile,$upload_path)){
        $_SESSION['write_error'] = '파일 업로드 success!';
    } else {
        $_SESSION['write_error'] = '파일 업로드 Fail ㅜㅜ';
    } 
} else {

};
    
//데이터베이스에 저장할 쿼리 엶
$con = mysqli_connect('localhost','root','1234','test');

if(!empty($origin_filename)){
$query = "INSERT INTO qna_board (title, content, date, name,phone,file,lock_post) VALUES ('$bTitle','$bContent','$date','$name','$bPhone','$new_filename','$lock_post')";
} else {
    $query = "INSERT INTO qna_board (title, content, date, name,phone,file,lock_post) VALUES ('$bTitle','$bContent','$date','$name','$bPhone',NULL,'$lock_post')";
}
if ($con->query($query)){
    echo "<h1>글쓰기 완료</h1>";
    echo "<p>작성한 글이 성공적으로 등록되었습니다.</p>";
    echo "<a href='qna_board.php'><button>목록으로 돌아가기</button></a>";
} else {
    echo "Error:".$sql."<br>".mysqli_error($con);
    echo "<a href='qna_write.php'><button>돌아가기</button></a>";
}
?>

동시에 qna_modify.php도 수정해준다

qna_write.php와 비슷하지만 수정하는 창에 맞게 단어를 바꾸면 된다

 

qna_modify.php 일부

<h1>문의 게시판 글수정</h1>
        <hr>
        <div id="boardwrite">
        <h6>문의게시판 글수정</h6>
        <br>
            <form action="./qna_modify_proc.php?number=<?php echo $bno; ?>" method="POST" enctype="multipart/form-data">
                <table id="boardwrite">
                    <thead>
                        <tr>
                            <th>제목</th>
                            <td class="title"><input style="width:700px;" type="text" name="bTitle" id="bTitle"></td>
                        </tr>
                        <tr>
                            <th>내용</th>
                            <td class="content"><textarea style="width:700px;height:400px;" name="bContent" id="bContent"></textarea></td>
                        </tr>
                        <tr>
                            <th>전화번호</th>
                            <td class="phone"><input placeholder="비밀글로 하시려면 작성해주세요" style="width:700px;" type="text" name="bPhone" id="bPhone"></td>
                        </tr>
                        <tr>
                            <th></th>
                            <td>
                                <!-- 게시글 잠금 기능 -->
                        <input type="checkbox" value="1" name="lockpost" id="lockpost"/> 비밀글 설정
                        </td>
                        </tr>    
                        </thead>
                        <tbody>
                        <tr>
                            <th></th>
                            <td>
                                <input type="file" name="board_file" />
                            <a href="qna_board.php" class="btnLIst btn"><div style="margin-left:300px;border:2px solid grey;">목록</div></a> 
                            <button 
                            style="background-color:pink" 
                            type="submit" 
                            onClick=
                            "return confirm('이대로 작성하시겠습니까? \n전화번호를 남기셨으면 차후 전화번호인증을 통해 게시글을 열람할 수 있습니다.')">
                            <div class="btnSEt">작성</div>
                            </button>
                        </td>
                        </tr>
                    
                        </tbody>
                    </table>
            <br>
            <div class="btnSEt">
                        <button type="submit" class="btnSubmit btn">수정 완료</button>
                        <a href="./qna_board.php" class="btnLIst btn">목록</a></div>
                    </form>

 

qna_modify에서 수정완료를 누르면 qna_modify_proc.php로 페이지 이동 후 완료한다

 

qna_modify_proc.php

<?php
session_start();

$con = mysqli_connect('localhost','root','1234','test');

//이 부분은 url로 전달받음
$bno = $_GET['number'];

//이건 로그인한 이후로 원래 있는거
if(isset($_SESSION['id'])){
    $username = $_SESSION['id'];
} else {
    $username = "익명";
}
//post로 전달받은 부분
$bPhone = $_POST['bPhone'];
$bTitle = $_POST['bTitle'];
$bContent = $_POST['bContent'];

if(isset($_POST['lockpost'])){
    $lock_post = 1 ;
} else {
    $lock_post = 0 ;
}

//파일 관련 변수
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_FILES['board_file'])){
    // $filesize=$_FILES['board_file']['size'];
    // $file_error=$_FILES['board_file']['error'];
    $tmpfile = $_FILES['board_file']['tmp_name'];
    $origin_filename = $_FILES['board_file']['name'];
    $allowed_mime_types =['image/jpeg','image/png','image/gif','application/zip','application/x-hwp','application/msword','application/pdf']; //mime허락된 형식
    $filename = iconv("UTF-8","EUC-KR",$_FILES['board_file']['name']);
    
    $timestamp = time();
    $new_filename = $timestamp.'_'.$filename;
    $file_mime_type = mime_content_type($tmpfile);
    // if(in_array($file_mime_type, $allowed_mime_types)){
        //파일 저장 경로
        $upload_path = './upload/'.$new_filename;
        if(move_uploaded_file($tmpfile,$upload_path)){
            $_SESSION['write_error'] = '파일 업로드 success!';
        } else {
            $_SESSION['write_error'] = '파일 업로드 Fail ㅜㅜ';
        } 
    } else {
    };


//쿼리문 실행
$query = "UPDATE qna_board SET name='$username',phone='$bPhone',title='$bTitle',content='$bContent',lock_post='$lock_post',file='$new_filename' WHERE number='$bno'";
$result = $con->query($query);

echo "수정이 완료되었습니다!<br><br>";
echo "<a href='qna_board.php'><button>게시판으로 돌아가기</button></a>";
?>

qna_write_proc.php와 비슷하지만

 

UPDATE~ SET 쿼리문을 사용한다

$query = "UPDATE qna_board SET name='$username',phone='$bPhone',title='$bTitle',content='$bContent',lock_post='$lock_post',file='$new_filename' WHERE number='$bno'";
$result = $con->query($query);

 

 

 

 

밑은 qna_board.php의 일부코드이다.

SQL쿼리문으로 게시글의 lock_post값을 보고 1이면 잠금 표시, 0이면 열어준다

 

그리고 문의게시글db내에 이름 조회가 안되면 익명으로 설정한다.

 

qna_board.php 일부

$title = $board['title']; //게시글 제목
$number = $board['number']; //게시글 번호
$lockpost = $board['lock_post'];
if(isset($board['name'])){
$name = $board['name']; //작성자
} else {
 $name = "익명"; 
}
<?php 
  $locking = "<img src='./lockpost.png' alt='lock' title='lock' width='20' height='20'";
  if($lockpost == '0'){ ?>
  <a href="./qna_read.php?number=<?php echo $board['number'];?>"><?php echo $title;?></td>
  <?php } else { ?>
  <a href="./ck_read.php?number=<?php echo $board['number'];?>"><?php echo $title,$locking;?></td>
  <?php } 
  ?>

$lockpost가 0이라면 qna_read.php로 바로 연결해주는 링크를 걸어주고

$lockpost가 1이라면 ck_read.php로 연결지어서 전화번호 인증을 거치는 창으로 연결지어주고

제목 옆에 잠금표시 이미지를 같이 띄워준다.

 

잠금 표시가 된 게시글을 클릭하면 ck_read.php페이지로 넘어가고

전화번호를 입력하는 창을 받게 된다.

ck_read.php의 코드입니다

 

ck_read.php

<?php
session_start();

$con = mysqli_connect('localhost','root','1234','test');
$id = $_GET['number'];
$query = "SELECT * FROM qna_board WHERE number='$id'";
$result = $con->query($query);
$q_board = $result -> fetch_array();

?>

<form method="POST" action="qna_read.php?number=<?php echo $id?>">
전화번호를 입력하세요<input type="password" name=phone>
<input type="submit" value="확인">
</form>

 

DB와 연결 후 form 태그를 통해 전화번호를 인증하는데 이 값은 qna_read.php로 전달되어

조건문을 통과하면 게시글을 보여주고 인증에 실패하면 문의 게시판 메인으로 되돌아간다.

 

 

인증에 성공하면 alert창을 보여주고 확인을 누르면 게시글을 보여준다.

 

게시글이 잘 보인다

 

만약 인증에 실패하면 문의 게시판 메인으로 되돌아가고 하단에 세션 메시지로 전화번호 인증에 실패했다는 문구가 뜬다.

아래는  qna_read.php의 코드 전문이다

 

qna_read.php

<?php
//세션 시작
session_start();
if(isset($_SESSION['id'])){
$login_id = $_SESSION['id'];
} else {
$login_id = "익명";
}

//클릭할 때 number GET으로 가져옴
$bno = $_GET['number'];

//전화번호 인증한거 변수로 저장
$pw_phone = $_POST['phone'];

//게시판 DB 연결
$con = mysqli_connect('localhost','root','1234','test');

//SQL Injection 대응
$boardlike_id = mysqli_real_escape_string($con,filter_var(strip_tags($bno), FILTER_SANITIZE_SPECIAL_CHARS));

//게시판 내용 보여주기
$query = "SELECT * FROM qna_board WHERE number='".$bno."'";
$result = $con->query($query);
$board = $result->fetch_array();

//문의게시판에는 조회수 기능 필요 없음
// $hit = $board['hit'];
// $hit = $hit + 1;
// $hit_query = "UPDATE board SET hit = '".$hit."' WHERE number ='".$bno."'";
// $hit_result = $con->query($hit_query);
if($board['lock_post']=='1'){
  if($board['phone']==$pw_phone){
    echo "<script>alert('전화번호 인증에 성공했습니다!')</script>";
  } else {
    $_SESSION['msg'] = "전화번호 인증에 실패했습니다";
    header("Location: ./qna_board.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>문의 게시판</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<?php
require('./nav.html');
?>

<!-- 게시글 불러오기 -->
<h2><?php echo $board['title']; ?></h2><HR>
<div>작성자 :<?php echo $board['name']; ?>
<?php echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;작성날짜 : ".$board['date']; ?></div>
<!-- 기준선 -->
<HR>
<?php 
$filename = explode('_', $board['file'])[1]; //타임스탬프를 제거 후 파일명만 분리
$download_url = 'download_proc.php?filename='.$board['file'];
echo '<p>파일 : <a href="'.$download_url.'">'.$filename.'</a></p>';
?>

<textarea style="width:100%; height:15rem;" readonly><?php echo $board['content']; ?></textarea>

<br><Br>
<a href="./qna_modify.php?number=<?php echo $board['number'];?>"><button class="btn btn-secondary">수정</button></a>
<a href="./qna_delete.php?number=<?php echo $board['number'];?>" onclick="return confirm('정말로 삭제하시겠습니까? 삭제 후에는 되돌릴 수 없습니다.')"><button class="btn btn-secondary">삭제</button></a>
<a href="./qna_board.php"><button class="btn btn-secondary">목록</button></a>
<p>

<?php
  if(isset($_SESSION['write_error'])){
    echo $_SESSION['write_error'];
    unset($_SESSION['write_error']);
  }
?>
</body>
</html>

 

 

 


비밀글 설정을 하지 않고 작성을 해보자

 

글쓰기 완료가 되었다는 문구가 뜨고 목록으로 돌아가면

 

잠금 표시도 안 뜨고

 

클릭하면 바로 게시글을 보여준다

 

로그인을 해서 세션아이디가 있다면 그 아이디로 글 작성이 된다

 


아직 미숙하지만 장장 3개월간 꾸준히 만든 결과물이고

뼈다귀같던 기존의 내 웹화면이 부트스트랩도 넣고 나름 커스텀한 css도 넣으면서 조금씩

바뀐 게 신기하기만 하다

몇달전 포스팅한 것과 지금 웹 화면을 비교해보면 감개무량하다

 

끝까지 마무리할 수 있어서 너무 뿌듯하다

 

이제 이 기반을 바탕으로 멋진 해커가 되자!