반응형
1. 홈페이지 구조
/var/www/html/bigju/
├── index.php (메인 화면: BIGJU 공부 페이지 + 회원가입/로그인/게시판 버튼)
├── register.php (회원가입)
├── login.php (로그인)
├── logout.php (로그아웃)
├── board.php (게시판 목록)
├── write.php (글쓰기 + 파일 업로드 + 글 비밀번호)
├── view.php (게시글 보기)
├── uploads/ (업로드 파일 저장 폴더)
├── db.php (DB 연결 파일)
└── table.sql (DB 테이블 생성 스크립트)
2.DB 정보
- DB: bigju
- 계정: root
- 비밀번호: 1234
- 테이블: users, posts
3. DB 생성 및 테이블 만들기
mysql -u root -p
CREATE DATABASE bigju;
USE bigju;
-- users 테이블
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE,
password VARCHAR(255),
email VARCHAR(100)
);
-- posts 테이블
CREATE TABLE posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
content TEXT,
filename VARCHAR(255),
password VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
------
외부 접속 허용
ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('1234');
FLUSH PRIVILEGES;
4.PHP파일 코드
db.php
<?php
$host = "localhost";
$user = "root";
$pass = "1234";
$dbname = "bigju";
$conn = new mysqli($host, $user, $pass, $dbname);
if ($conn->connect_error) {
die("DB 연결 실패: " . $conn->connect_error);
}
?>
5. index.php
<?php
session_start();
// 세션 유지 시간 (초) ? 예: 30분 = 1800초
$timeout = 180;
// 마지막 활동 시간 저장 또는 갱신
if (isset($_SESSION['LAST_ACTIVITY'])) {
// 현재 시간과 마지막 활동 시간 차이 계산
if (time() - $_SESSION['LAST_ACTIVITY'] > $timeout) {
// 타임아웃 시 세션 종료 및 강제 로그아웃
session_unset();
session_destroy();
header("Location: login.php?timeout=1"); // 원하는 페이지로 리다이렉트
exit;
}
}
// 마지막 활동 시간 업데이트
$_SESSION['LAST_ACTIVITY'] = time();
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>BIGJU 공부 페이지</title>
<style>
body { text-align: center; margin-top: 100px; font-size: 20px; }
h1 { font-size: 40px; }
a { display: block; margin: 20px; font-size: 24px; }
</style>
</head>
<body>
<h1>BIGJU 공부 페이지</h1>
<?php if(isset($_SESSION['user'])): ?>
<p><strong><?= htmlspecialchars($_SESSION['user']) ?></strong> 님 환영합니다!</p>
<a href="board.php">게시판</a>
<a href="logout.php">로그아웃</a>
<?php else: ?>
<a href="register.php">회원가입</a>
<a href="login.php">로그인</a>
<?php endif; ?>
</body>
</html>
6. register.php
include 'db.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$email = $_POST['email'];
$stmt = $conn->prepare("INSERT INTO users (username, password, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $username, $password, $email);
$stmt->execute();
echo "<script>alert('회원가입 완료!'); location.href='index.php';</script>";
}
?>
<form method="post">
<h2>회원가입</h2>
아이디: <input type="text" name="username" required><br>
비밀번호: <input type="password" name="password" required><br>
이메일: <input type="email" name="email" required><br>
<button type="submit">가입하기</button>
</form>
7. login.php
<?php
include 'db.php';
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $conn->prepare("SELECT * FROM users WHERE username=?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user'] = $username;
echo "<script>alert('로그인 성공!'); location.href='index.php';</script>";
} else {
echo "<script>alert('로그인 실패!'); history.back();</script>";
}
}
?>
<form method="post">
<h2>로그인</h2>
아이디: <input type="text" name="username" required><br>
비밀번호: <input type="password" name="password" required><br>
<button type="submit">로그인</button>
</form>
8.logout.php
<?php
session_start();
session_destroy();
echo "<script>alert('로그아웃되었습니다.'); location.href='index.php';</script>";
9. board.php (게시판 목록)
<?php
session_start();
if (!isset($_SESSION['user'])) {
echo "<script>alert('로그인 후 이용하세요.'); location.href='login.php';</script>";
exit;
}
include 'db.php';
$result = $conn->query("SELECT * FROM posts ORDER BY id DESC");
?>
<h2>게시판</h2>
<a href="write.php">글쓰기</a>
<table border="1" width="600">
<tr><th>번호</th><th>제목</th><th>작성일</th></tr>
<?php while($row = $result->fetch_assoc()): ?>
<tr>
<td><?= $row['id'] ?></td>
<td><a href="view.php?id=<?= $row['id'] ?>"><?= htmlspecialchars($row['title']) ?></a></td>
<td><?= $row['created_at'] ?></td>
</tr>
<?php endwhile; ?>
</table>
10. write.php (글쓰기)
<?php
include 'db.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = $_POST['title'];
$content = $_POST['content'];
$password = password_hash($_POST['post_password'], PASSWORD_DEFAULT);
$upload_dir = "uploads/";
if (!is_dir($upload_dir)) mkdir($upload_dir);
$file_to_save = '';
if (isset($_FILES['file']) && $_FILES['file']['error'] === 0) {
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
$new_file_name = uniqid('file_', true) . '.' . $ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir . $new_file_name)) {
$file_to_save = $new_file_name;
} else {
echo "<script>alert('파일 업로드 실패! 폴더 권한 및 파일명을 확인하세요.'); history.back();</script>";
exit;
}
}
$stmt = $conn->prepare("INSERT INTO posts (title, content, filename, password) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $title, $content, $file_to_save, $password);
$stmt->execute();
echo "<script>alert('글 작성 완료!'); location.href='board.php';</script>";
}
?>
<form method="post" enctype="multipart/form-data">
제목: <input type="text" name="title" required><br>
내용: <textarea name="content" required></textarea><br>
파일업로드: <input type="file" name="file"><br>
글 비밀번호: <input type="password" name="post_password" required><br>
<button type="submit">작성하기</button>
</form>
11. view.php (게시글 보기)
<?php
include 'db.php';
$id = (int)$_GET['id']; // 보안: int형으로 강제 캐스팅
$post = $conn->query("SELECT * FROM posts WHERE id=$id")->fetch_assoc();
echo "<h2>" . htmlspecialchars($post['title']) . "</h2>";
echo "<p>" . nl2br(htmlspecialchars($post['content'])) . "</p>";
if ($post['filename']) {
$file = htmlspecialchars($post['filename']);
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
$img_types = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
if (in_array($ext, $img_types)) {
// 이미지 파일이면 썸네일과 링크
echo "<p><a href='uploads/$file' target='_blank' rel='noopener noreferrer'>
<img src='uploads/$file' style='max-width:300px; height:auto;'></a></p>";
}
// 다운로드 링크는 공통으로 표시
echo "<p>첨부파일: <a href='uploads/$file' download>$file</a></p>";
}
?>
12. delete.php ( 게시글 삭제 가능)
<?php
session_start();
if (!isset($_SESSION['user']) || $_SESSION['user'] !== 'bigju') {
echo "<script>alert('권한이 없습니다.'); location.href='index.php';</script>";
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
include 'db.php';
$id = (int)$_POST['id'];
// 삭제할 게시물 정보 조회 (첨부파일 있으면 삭제 위해)
$stmt = $conn->prepare("SELECT filename FROM posts WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$post = $result->fetch_assoc();
if ($post) {
// 첨부파일이 있으면 파일 삭제
if ($post['filename'] && file_exists("uploads/" . $post['filename'])) {
unlink("uploads/" . $post['filename']);
}
// 게시물 삭제
$del = $conn->prepare("DELETE FROM posts WHERE id = ?");
$del->bind_param("i", $id);
$del->execute();
echo "<script>alert('게시물이 삭제되었습니다.'); location.href='board.php';</script>";
exit;
} else {
echo "<script>alert('게시물을 찾을 수 없습니다.'); location.href='board.php';</script>";
exit;
}
} else {
header("Location: board.php");
exit;
}
12. 폴더 권한 설정
sudo mkdir /var/www/html/bigju/uploads
sudo chmod 777 /var/www/html/bigju/uploads
sudo chown -R www-data:www-data /var/www/html/bigju
sudo mkdir /var/www/html/bigju
sudo chown -R www-data:www-data /var/www/html/bigju
sudo chmod -R 755 /var/www/html/bigju
반응형
'SW > 서버보안' 카테고리의 다른 글
Apche WAF 설치하여 웹 서비스 보안 설정 (0) | 2025.07.19 |
---|---|
Rocky GeoIP 방화벽 설치 방법 해외 공격 차단 [maxmind] (0) | 2025.03.19 |
Windows server 2008 R2 / window 7 보안 업데이트 방법 [윈도우 인증 오류 / 서비스 종료 수동 업데이트 / 0x80072F8F / 8024001F / ] (0) | 2022.04.19 |
서버 보안가이드 정리 (0) | 2021.11.12 |
해킹 의심해보기 (0) | 2021.11.11 |
댓글