목차
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> <input type="text" name="id"></td>
</tr>
<tr>
<td width="1000"><p align="center">패스워드</p></td>
<td> <input type="password" name="userpasswd"></td>
</tr>
<tr>
<td width="100"><p align="center">별명</p></td>
<td> <input type="text" name="cname"></td>
</tr>
<tr>
<td width="100"><p align="center">이름</p></td>
<td> <input type="text" name="name"></td>
</tr>
<tr>
<td width="100"><p align="center">전자우편</p></td>
<td> <input type="text" name="email"></td>
</tr>
<tr>
<td width="100"><p align="center">전화</p></td>
<td> <input type="text" name="tel"></td>
</tr>
<tr>
<td width="100"><p align="center">주소</p></td>
<td> <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 id=$id 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> <input type='text' name='id'></td>
<td width='80'>passwd: </td>
<td> <input type='password' name='userpasswd'></td>
<td> <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>" : "<< ") . "
" . ($login == 1 && $n < $row_num ? "<a href='./view.php?start=$n&search=$search'>>></a>" : ">> ") . "
<form name='search' method='get' action='view.php' style='display: inline;'>
<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="확인">
<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__); ?>
'일일 정리' 카테고리의 다른 글
Network Layer 구조, 해킹 실습 John the Ripper (0) | 2025.04.09 |
---|---|
패킷 분석 실습 서버 구축, Wireshark, 패킷의 이해 (0) | 2025.04.09 |
게시판 웹브라우저 프로그래밍, PHP 보안 - 스크립트 공격 방지 (0) | 2025.04.03 |
웹브라우저 구성 및 모델링 (0) | 2025.04.02 |
오라클 클라이언트 - 아파치 - PHP 연동, php.ini 보안 설정 (1) | 2025.03.31 |