일일 정리

게시판 웹브라우저 프로그래밍

mysecurity 2025. 4. 4. 23:53

목차

1. 게시판 웹브라우저 프로그래밍

 

 

1. 게시판 웹브라우저 프로그래밍

● 회원가입 id.html, id.php

// id.html //

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title> ID</title>
</head>
<body bgcolor="white" text="black" link="blue" vlink="purple" alink="red">
    <form name="insert" action="id.php" method="POST">      
    <center>                                                   
        <table border="0" width="300" >
            <tr>
                <td colspan="2">
                    <hr style="border: 10px solid #0033FF; margin: 10px 0;">
                </td>
            </tr>
            <tr>
                <td width="100"><p align="center">id</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="id"></td>
            </tr>
            <tr>
                <td width="1000"><p align="center">패스워드</p></td>
                <td>&nbsp;&nbsp;<input type="password" name="userpasswd"></td>
            </tr>
            <tr>
                <td width="100"><p align="center">별명</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="cname"></td>
            </tr>
            <tr>
                <td width="100"><p align="center">이름</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="name"></td>
            </tr>
            <tr>
                <td width="100"><p align="center">전자우편</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="email"></td>
            </tr>    
            <tr>
                <td width="100"><p align="center">전화</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="tel"></td>
            </tr>
            <tr>
                <td width="100"><p align="center">주소</p></td>
                <td>&nbsp;&nbsp;<input type="text" name="addr"></td>
            </tr>    
            <tr>
                <td></td>
                <td align='center'>
                    <input type="submit" name="확인" value="확인" style="margin-right: 20px;">
                    <input type="button" name="취소" value="취소">
                </td>
            </tr>
                <tr>
                    <td colspan="2">
                        <hr style="border: 10px solid #0033FF; margin: 10px 0;">
                    </td>
                </tr>
         
            <tr>
                <td align="left">
                    <a href="view.php">[목록으로]</a>
                </td>
            </tr>
        </table>
        </center>
    </form>
</body>
</html>
<br><hr><br>
<?  show_source(__FILE__); ?>

 

// id.php //

<html>
    <head>
        <title>id_in.php</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
<body>

<?     

    session_start();
    require('conn.php');    // $conn

    $id = strip_tags(htmlspecialchars($_POST['id'], ENT_QUOTES, 'UTF-8'));
    $userpasswd = strip_tags(htmlspecialchars($_POST['userpasswd'], ENT_QUOTES, 'UTF-8'));
    $name = strip_tags(htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8'));
    $cname = strip_tags(htmlspecialchars($_POST['cname'], ENT_QUOTES, 'UTF-8'));
    $tel = strip_tags(htmlspecialchars($_POST['tel'], ENT_QUOTES, 'UTF-8'));
    $addr = strip_tags(htmlspecialchars($_POST['addr'], ENT_QUOTES, 'UTF-8'));
    $email = strip_tags(htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8'));

    
    $sql="insert into id (ino, id, passwd, name, cname, tel, addr, email)
            values (id_ino_seq.nextval, '$id', RAWTOHEX(STANDARD_HASH('$userpasswd'||'$id', 'SHA256')), '$name', '$cname', '$tel', '$addr', '$email')";

    $result=oci_parse($conn,$sql);     
    $re = oci_execute($result, OCI_NO_AUTO_COMMIT);

    if ($re) {
        // 명시적으로 커밋 수행
        oci_commit($conn);
        echo("정상 입력 되었습니다.");
    } else {
        // 실패 시 롤백도 가능
        oci_rollback($conn);
        echo("입력 실패 - 롤백 처리되었습니다.");
    }                          
    oci_free_statement($result);
    oci_close($conn);
 
    echo(" <meta http-equiv='Refresh' content = '1; URL=view.php'>");
?>
<br><hr><br>
<?  show_source(__FILE__); ?>
</body>
</html>
<br><hr><br>
<?  show_source(__FILE__); ?>

회원가입 구현 화면

 

● 로그인 상태 확인 login.php

게시글 작성 화면이나 게시글 상세 화면과 같은 경우, 일반적인 접근 시 로그인 상태에서만 접근할 수 있도록 작성하였다.

그러나 url주소를 직접 입력하여 접근 시 비 로그인 상태에서도 접근이 가능하므로 login.php를 이용하여 로그인이 된 사용자만을 접근하도록 한다.

 

각 프로그램마다 로그인 여부를 확인하는 방식으로 작성할 수 있으나, 실전에서는 작성되는 프로그램이 매우 많아 이는 현실적으로 어려운 방식이다.

그러므로 다음과 같이 로그인을 확인하는 프로그램을 따로 작성하여 필요 시 호출하는 방식으로 이용하는 것이 일반적이다.

// login.php //

<?
  $id = $_SESSION["id"];                 
  $userpasswd = $_SESSION["userpasswd"]; 
  if(empty($id)){
    $login = 0;
  }
  else {
    $sql="select id, passwd from id where id = '$id' and passwd = RAWTOHEX(STANDARD_HASH('$userpasswd'||'$id', 'SHA256'))";
    // echo("sql = $sql<br>");  
    $result=oci_parse($conn,$sql);
    $re=oci_execute($result);

    if($row=oci_fetch_array($result, OCI_ASSOC)){
      $_SESSION["id"] = $id;
      $_SESSION["userpasswd"] = $userpasswd;
      $login = 1;                        // $row_num이 1 이면 로그인 성공, $login은 1.
    }
    else{
      $login = 0;                        // $row_num이 1 이 아니면 부정.
      $_SESSION["id"] = '';              // 안전을 위해 세션 인증 변수 초기화
      $_SESSION["userpasswd"] = '';              // 필수 사항은 아님
    }
  }
  if($login==0)
    { echo(" <script>
             window.alert('로그인이 필요합니다.');
              history.go(-1);
              </script>
           ");
      exit;
    }
//   echo("login=$login &nbsp; id=$id  &nbsp; pw=$pw <br>");
?>

 

 

● 게시글 목록  view.php

// view.php //

<html>
    <head>
        <title>view.php</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
<body>
<?
  session_start();
  
  if(empty($_GET["logout"])){}                //db연결한거
  else {
      $_SESSION["id"] = null;
      $_SESSION["userpasswd"] = null;
      }    
  
  require('conn.php');

  $id = $_SESSION["id"];
  $userpasswd = $_SESSION["userpasswd"];
  
  $sql="select * from id 
        where id = '$id' 
        and passwd = RAWTOHEX(STANDARD_HASH('$userpasswd'||'$id', 'SHA256'))";

  $result=oci_parse($conn,$sql);
  $re=oci_execute($result);

  if($row=oci_fetch_array($result, OCI_ASSOC)){
    $login = 1;                         // $row_num이 1 이면 로긴 성공, $login은 1.
  }
  else{
    $login = 0;                        // $row_num이 1 이 아니면 부정.
  }

   if($login == 1){
                            // 로그인 상태
                echo("<table border='0' align='center'>
                <tr>
                    <td width='1150'  align='right'>
                    {$row['CNAME']} 님을 환영합니다.
                    <a href=view.php?logout=$row>로그아웃</a>
                    <a href=insert.html>글쓰기</a>
                    </td>
                </tr>
                </table>");
      }   
   else{                                  // 비로그인 상태
      echo("<form name='login' action='check.php' method='POST'>
            <table border='0'align='right' width='700'>
                  <tr>
                        <td></td>
                        <td width='500' style='padding-right: 10px;'>
                        <a href=./id.html>회원가입</a>
                        </td>
                        <td width='80'>ID: </td>
                        <td>&nbsp;&nbsp;<input type='text' name='id'></td>
                        <td width='80'>passwd: </td>
                        <td>&nbsp;&nbsp;<input type='password' name='userpasswd'></td>
                        <td>&nbsp;&nbsp;<input type='submit' name='로그인' value='로그인'></td>
                  </tr>    
            </table>
            </form>
           ");
      } 
    echo("<br><br><hr><br>");                 
// =========================== 검색
$search = $_GET['search'];
if (empty($search))                
   {
    $sql="select bno, sub, cname, to_char(bdate, 'yyyy/mm/dd') bdate, hit 
          from board, id where id.ino = board.ino order by bno";
   }   
else                                  
   { 
    $sql="select bno, sub, cname, to_char(bdate, 'yyyy/mm/dd') bdate, hit 
          from board, id where id.ino = board.ino and sub like '%{$search}%' order by bno";
   }
// ===========================
                                                                                       
  $result=oci_parse($conn,$sql);        
  oci_execute($result);

  $row_num=ocifetchstatement($result,$row);
  
  $scale=5;                           // 화면에 출력할 행의 개수
  $start = $_GET['start'];       
  if (empty($start)){ $start=0;}    // 첫 화면은 0에서 시작, 배열의 키값은 0에서 시작
  echo("<table border='0' align='center'>
            <tr bgcolor='0033FF'>
                <td width='80'><p align='center'>번호</p></td> 
                <td width='800'><p align='center'>제목</p></td>
                <td width='80'><p align='center'>작성자</p></td>
                <td width='100'><p align='center'>날짜</p></td> 
                <td width='80'><p align='center'>조회</p></td>   
            </tr>
            ");

  for ($i = $start ; $i < ($start + $scale); $i++) {
    if ($i < $row_num) {                                // 로그인 상태일 경우 게시글 제목을 링크로 만들기
        if ($login == 1) {  // 세션에 id가 있을 때
            $sub = "<a href='content.php?bno={$row['BNO'][$i]}'>" . $row['SUB'][$i] . "</a>";
        } else {
            // 비로그인 상태에서는 제목은 텍스트로만 표시
            $sub = $row['SUB'][$i];
        }
        $viewbno = $i + 1;
        echo ("<tr>
                <td width='50'><p align='center'>{$viewbno}</p></td>
                <td width='800'><p align='center'>{$sub}</p></td>
                <td width='20'><p align='center'>{$row['CNAME'][$i]}</p></td>
                <td width='20'><p align='center'>{$row['BDATE'][$i]}</p></td>
                <td width='50'><p align='center'>{$row['HIT'][$i]}</p></td>
              </tr>");
    }
}      
oci_free_statement($result);  
oci_close($conn);

$p=$start-$scale;     // 이전 화면의 시작 위치
$n=$start+$scale;     // 다음 화면의 시작 위치/               
echo("<tr>
        <td colspan='5' style='text-align: right; padding-right: 10px;'>
            " . ($login == 1 && $p >= 0 ? "<a href='./view.php?start=$p&search=$search'><<</a>" : "&lt;&lt;&nbsp;&nbsp;") . "
            " . ($login == 1 && $n < $row_num ? "<a href='./view.php?start=$n&search=$search'>>></a>" : "&gt;&gt;&nbsp;&nbsp;") . "
            <form name='search' method='get' action='view.php' style='display: inline;'>
                &nbsp;<input type='text' name='search' style='margin-right: 5px;'>
                <input type='submit' value='확인'>
            </form>
        </td>
      </tr>
      </table>
      ");
?>
</body>
</html>
<br><br><br><br><hr>
<?show_source(__FILE__);?>

비 로그인 시 게시글 목록 구현 화면

 

로그인 시 게시글 목록 구현 화면

 

● 게시글 작성 insert.html, insert.php

// insert.html //

<?
    session_start();
    require('conn.php');  // $conn
    require('login.php');
?>
<html>

<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>insert</title>
</head>

<body>

    
    <table width="600" align="center" cellspacing="0" cellpadding="5" border="0">
        <tr bgcolor="#0000FF">
            <td colspan="2" align="center" style="color:white;"><b>글을 써보아요</b></td>
        </tr>
        <tr bgcolor="#DDEEFF">
            <td>
                <form action="insert.php" method="post">
                    <table width="100%" cellspacing="5" cellpadding="5" border="0">
                        <tr>
                            <td width="15%">제목</td>
                            <td><input type="text" name="sub" size="66"></td>
                        </tr>
                        <tr>
                            <td width="15%">내용</td>
                            <td><textarea name="content" rows="10" cols="68"></textarea></td>
                        </tr>
                    </table>
                    <table width="100%" cellspacing="5" cellpadding="5" border="0">
                        <tr>
                            <td align="right">
                                <input type="submit" value="확인">&nbsp;&nbsp;
                                <input type="reset" value="취소">
                            </td>
                        </tr>
                    </table>
                </form>
            </td>
        </tr>
        <tr bgcolor="#0000FF">
            <td colspan="2"></td>
        </tr>
    </table>
    <div style="text-align: center;">
        <a href="view.php" style="text-decoration: none; color: blue; display: block; margin-top: 10px;">[목록으로]</a>
    </div>
</body>

</html>
<br><hr><br>
<?  show_source(__FILE__); ?>

 

// insert.php //

<html>
    <head>
        <title>insert.php</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
<body>

<?
    session_start();
    require('conn.php');  // $conn
    require('login.php');
    
    $sub = strip_tags(htmlspecialchars($_POST['sub'], ENT_QUOTES, 'UTF-8'));
    $content = strip_tags(htmlspecialchars($_POST['content'], ENT_QUOTES, 'UTF-8'));
    $id = $_SESSION['id'];
    $userpasswd = $_SESSION['userpasswd'];
    



$sql = "select * from id 
        where id = '$id'
        and passwd = RAWTOHEX(STANDARD_HASH('$userpasswd'||'$id', 'SHA256'))";

$result = oci_parse($conn, $sql);        
$re = oci_execute($result);

$row = oci_fetch_array($result, OCI_ASSOC);

    $ino = $row['INO'];


    $sql="insert into board (bno, sub, bdate, hit, ino)
            values (board_bno_seq.nextval, '$sub', trunc(sysdate), 0, '$ino')";

    $result1=oci_parse($conn,$sql);     
    $re1 = oci_execute($result1, OCI_NO_AUTO_COMMIT);

    $sql="insert into content (bno, content)
            values (board_bno_seq.currval, '$content')";
    $result2=oci_parse($conn,$sql);     
    $re2 = oci_execute($result2, OCI_NO_AUTO_COMMIT);
    

    if ($re1 && $re2) {
        // 명시적으로 커밋 수행
        oci_commit($conn);
        echo("정상 입력 되었습니다.");
        echo(" <meta http-equiv='Refresh' content = '1; URL=view.php'>");
    } else {
        // 실패 시 롤백도 가능
        oci_rollback($conn);
        echo("입력 실패 - 롤백 처리되었습니다.");
        echo(" <meta http-equiv='Refresh' content = '1; URL=insert.html'>");
    }                          
    oci_free_statement($result1);
    oci_free_statement($result2);
    oci_close($conn);
 
    
?>

</body>
</html>
<br><hr><br>
<?  show_source(__FILE__); ?>

게시글 작성 구현 화면

 

● 게시글 상세 content.php

// content.php //

<?
session_start();
require('conn.php');
require('login.php');

$bno = $_GET["bno"];
//echo($bno);

$sql_update_hit = "UPDATE board SET hit = hit + 1 WHERE bno = :bno"; // 조회수 상승 기능
$stmt_update = oci_parse($conn, $sql_update_hit);
oci_bind_by_name($stmt_update, ":bno", $bno);
oci_execute($stmt_update);

$sql="select board.bno, sub, cname, to_char(bdate, 'yyyy/mm/dd') bdate, content
          from board, id, content where id.ino = board.ino and board.bno = content.bno and board.bno = '$bno' order by bno";
$result=oci_parse($conn,$sql);
$re=oci_execute($result);
$row = oci_fetch_array($result,OCI_ASSOC);


$sub = $row['SUB']; // 게시글 제목 
$cname = $row['CNAME'];   // 작성자 
$bdate = $row['BDATE']; // 작성일 
$content = $row['CONTENT']; // 게시글 내용 
//echo($sub);
?>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시글 상세보기</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f7fa;
            margin: 0;
            padding: 0;
        }

        .container {
            width: 60%;
            margin: 50px auto;
            padding: 30px;
            background-color: #ffffff;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }

        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
        }

        .post-header {
            margin-bottom: 30px;
        }

        .post-header div {
            margin-bottom: 10px;
            font-size: 16px;
        }

        .post-header .title {
            font-size: 24px;
            font-weight: bold;
            color: #333;
        }

        .post-header .author,
        .post-header .date {
            color: #777;
        }

        .post-content {
            font-size: 18px;
            line-height: 1.6;
            color: #444;
        }

        .links {
            display: flex;
            justify-content: flex-end;
            gap: 20px;
            margin-top: 30px;
        }

        .back-link, .delete-link {
            font-size: 16px;
            color: #007bff;
            text-decoration: none;
        }

        .back-link:hover, .delete-link:hover {
            text-decoration: underline;
        }

        .delete-link {
            color: #f44336; /* Delete link color */
        }

    </style>
</head>
<body>

    <div class="container">
        <div class="post-header">
            <!-- 제목 -->
            <div class="title"><?php echo "제목: " . $sub; ?></div>

            <!-- 작성자 및 날짜 -->
            <div class="author"><?php echo "작성자: " . $cname; ?></div>
            <div class="date"><?php echo "작성일: " . $bdate; ?></div>
        </div>

        <!-- 내용 -->
        <div class="post-content">
            <p>
                <?php echo $content; ?>
            </p>
        </div>

        <!-- 목록으로 돌아가기와 삭제 링크 -->
        <div class="links">
            <a href="view.php" class="back-link">목록으로 돌아가기</a>
            <a href="del.php?bno=<?php echo $bno; ?>" class="delete-link">게시글 삭제</a>
        </div>
    </div>

</body>
</html>


<br><hr><br>
<?  show_source(__FILE__); ?>

게시글 상세 구현 화면