※해당 게시글은 취약점 진단 목적의 웹 서비스 구축을 위한 부분으로, 일반적인 웹 서비스 개발 목적과는 다름을 참고해주시면 감사하겠습니다.
※일반적으로는 게시판 등의 기능을 구현하고 HTTPS 설정을 할 수 있으나, 개발 목적 상 초기에는 로그인 기능까지만 필요하였기에 HTTPS 설정을 우선함
※차후 테스트 목적으로 파일 업로드 등을 포함한 게시판 기능이 일부 필요하여 추가 진행
1.구축 환경
| 구분 | 설명 | 비고 |
| 운영체제 | Ubuntu 22.04 x64 (6.2.0-36-generic) | |
| 하드웨어 | VM | |
| 서버 운영환경 | Node v12.22.9 / npm 8.5.1 / express 4.18.2 mongoose 8.0.3 ejs 3.1.9 |
|
| 데이터베이스 | MongoDB Community Edition 7.0.4 |
2.구축 과정
1)게시판 필요 기능 구분
(1) 게시글 전체 목록 표시
| 필요 기능 | 설명 및 요구 사항 |
| 게시글 목록 | 번호 / 제목 / 작성자 / 작성일의 정보로 표시되는 전체 게시글 목록 '제목' 선택으로, 게시글 열람 |
| 글쓰기 버튼 | '글쓰기' 버튼 선택으로, 게시글 쓰기 기능으로 이동 |
(2) 게시글 쓰기
| 필요 기능 | 설명 및 요구 사항 |
| 제목 쓰기 | 게시글의 제목을 입력받기 위한 기능 |
| 내용 쓰기 | 게시글의 내용을 입력받기 위한 기능 |
| 파일 업로드 | 게시글에 포함될 첨부 파일 업로드 기능 |
(3) 게시글 열람
| 필요 기능 | 설명 및 요구 사항 |
| 제목 표시 | 작성된 게시글의 제목 표시 |
| 내용 표시 | 작성된 게시글의 내용 표시 |
| 첨부파일 표시 | 작성된 게시글에 포함된 첨부파일명 표시 |
| 파일 다운로드 | 작성된 게시글에 포함된 첨부파일 다운로드 |
2) 게시글 전체 목록 표시 구현
(1) 소스코드
// 게시판 라우트
app.get('/board', requireLogin, async (req, res) => {
try {
// MongoDB 클라이언트 연결
await client.connect();
// 'WebApplication_01' 데이터베이스 및 'Posts' 컬렉션 선택
const database = client.db('WebApplication_01');
const postsCollection = database.collection('Posts');
// 최근 작성된 게시글 중 최대 10개 가져오기
const posts = await postsCollection.find().sort({ timestamp: -1 }).limit(10).toArray();
// 게시판 템플릿 렌더링
res.render('board', { posts });
} catch (error) {
console.error('게시글 조회 오류:', error);
res.status(500).send('서버 오류');
} finally {
// MongoDB 클라이언트 연결 종료
await client.close();
}
});
(2) 예시

3)게시글 쓰기
(1) 소스코드
app.post('/board_write', upload.single('file'), requireLogin, async (req, res) => {
const { title, content } = req.body;
const uploadedFile = req.file;
try {
// MongoDB 클라이언트 연결
await client.connect();
// 'WebApplication_01' 데이터베이스 및 'Posts' 컬렉션 선택
const database = client.db('WebApplication_01');
const postsCollection = database.collection('Posts');
// 새로운 게시글 생성
const newPost = {
title,
content,
author: req.session.user,
timestamp: new Date(),
file: uploadedFile ? uploadedFile.originalname : null,
};
// 데이터베이스에 새로운 게시글 삽입
await postsCollection.insertOne(newPost);
// 게시판 페이지로 리다이렉트
res.redirect('/board');
} catch (error) {
console.error('게시글 작성 오류:', error);
res.status(500).send('서버 오류');
} finally {
// MongoDB 클라이언트 연결 종료
await client.close();
}
});
(2) 예시

4)게시글 열람
(1) 소스코드
// 게시글 보기 페이지
app.get('/board/:postId', requireLogin, async (req, res) => {
const postId = req.params.postId;
console.log('Requested Post ID:', postId);
//게시글 ID를 Object 타입으로 재선언
const postIdObject = new ObjectId(postId);
try {
// MongoDB 클라이언트 연결
await client.connect();
// 'WebApplication_01' 데이터베이스 및 'Posts' 컬렉션 선택
const database = client.db('WebApplication_01');
const postsCollection = database.collection('Posts');
// postId에 해당하는 게시글 조회
//const post = await postsCollection.findOne({ _id: postId });
const post = await postsCollection.findOne({ _id: postIdObject });
console.log('Requested Post :', post); // 이 부분을 추가
if (post) {
res.render('view_post', { post });
} else {
res.status(404).send('게시글을 찾을 수 없습니다.');
}
} catch (error) {
console.error('MongoDB 연결 오류:', error);
res.status(500).send('서버 오류');
} finally {
// MongoDB 클라이언트 연결 종료
await client.close();
}
});
(2) 예시

3.예외 처리
1) 게시글이 난수 값으로 생성되는 ObjectId로 링크가 생성되는 점은 확인하였으나, 개발 목적 상 현재 필요한 부분이 아니기에 수정하지 않음
2) 업로드되는 파일명, 다운로드 링크 정보 및 업로드된 Node 서버 내 저장되는 파일명이 원본 파일명으로 저장되나 개발 목적 상 수정하지 않음

3) 업로드된 파일 중 일부 파일은 사용자 환경에서 실행되는 부분으로 취약점이 발생하나 개발 목적 상 수정하지 않음

'개발' 카테고리의 다른 글
| [WEB] Node.js 웹 사이트 구축 5 (Flutter 앱_프로젝트 설정) (0) | 2024.01.24 |
|---|---|
| [WEB] Node.js 웹 사이트 구축 3 (HTTPS 적용) (0) | 2024.01.19 |
| [WEB] Node.js 웹 사이트 구축 2 (로그인 기능 구현) (0) | 2024.01.15 |
| [WEB] Node.js 웹 사이트 구축 1 (환경 구성) (0) | 2024.01.05 |
| [Python] m3u8 스트리밍 영상 다운로드 (Feat.불법 다운로드 대응) (0) | 2023.06.08 |