본문 바로가기

개발

[WEB] Node.js 웹 사이트 구축 3 (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)SSL/TLS 인증서 생성

 - SSL/TLS 인증서는 무료로 제공되는 'Lets Encrypt'를 이용하는 경우와, 'openssl' 등을 이용하여 사설 인증서를 생성할 수 있으나 개발 목적을 위해 'openssl'을 이용한 자체 인증서를 생성

 - Let's Encrypt 는 인터넷망에 연결된 웹 사이트에 보다 더 많은 암호화된 연결을 제공하는데 목적을 가짐

 

(1) 인증서 생성

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

 

(2)생성된 개인키 key.pem 에 입력된 비밀번호 제거

 -  비밀번호를 제거하지 않으면 서버 실행 시마다 비밀번호 입력을 요구, 번거로움과 'nodemon'에서 구동 시 비밀번호 입력이 되지 않아 에러가 발생

openssl rsa -in key.pem.ori -out key.pem

 

2)app.js에 HTTPS 적용

 - 이전 소스코드에서 'const app = express();'로 실행되는 서버는 HTTP 서버로, HTTPS 서버 생성 및 실행으로 변경 필요

#https 사용과, 키 값을 호출하도록 fs 모듈 설정
const https = require('https');
const fs = require('fs');
const path = require('path');

#키 경로 설정
const keyPath = '[경로]/ssl/key.pem';
const certPath = '[경로]//ssl/cert.pem';

const key = fs.readFileSync(keyPath, 'utf8');
const cert = fs.readFileSync(certPath, 'utf8');

const credentials = { key: key, cert: cert };

#HTTPS 서버 생성 및 실행
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(PORT, () => {
  console.log(`HTTPS 서버가 ${PORT} 포트에서 실행 중입니다.`);
});

 

3)변경된 app.js 전체 소스코드

// app.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const { MongoClient } = require('mongodb');
const path = require('path');
const https = require('https');
const fs = require('fs');
const PORT = 8443;
const sessionSecretKey = 'SecretKey';

const app = express();

app.set('view engine', 'ejs'); // EJS를 사용하도록 설정
app.set('views', __dirname + '/views'); // views 디렉토리 경로 설정

app.use(session({ secret: sessionSecretKey, resave: false, saveUninitialized: true }));
app.use(bodyParser.urlencoded({ extended: true }));

// MongoDB 연결 정보
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri, { useUnifiedTopology: true });

const keyPath = '[경로]/ssl/key.pem';
const certPath = '[경로]/ssl/cert.pem';

const key = fs.readFileSync(keyPath, 'utf8');
const cert = fs.readFileSync(certPath, 'utf8');

const credentials = { key: key, cert: cert };

// 미들웨어 설정
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// 라우트 및 컨트롤러
app.get('/', (req, res) => {
  res.send('Welcome to the home page!');
});

app.get('/login', (req, res) => {
  res.render('login'); // EJS 템플릿을 사용하여 login.ejs 렌더링
});

// 로그인 처리
app.post('/login', async (req, res) => {
  const { username, password } = req.body;

  try {
    // MongoDB 클라이언트 연결
    await client.connect();

    // 'WebApplication_01' 데이터베이스 및 'Member' 컬렉션 선택
    const database = client.db('WebApplication_01');
    const memberCollection = database.collection('Member');

    // 입력한 username과 password로 사용자 조회
    const user = await memberCollection.findOne({ username, password });

    if (user) {
      // 사용자 정보가 일치하면 세션에 사용자 정보 저장
      req.session.user = username;
      res.redirect('/dashboard'); // 로그인 성공 시 대시보드로 리다이렉트
    } else {
      // 사용자 정보가 일치하지 않으면 로그인 페이지로 리다이렉트
      res.redirect('/login');
    }
  } catch (error) {
    console.error('MongoDB 연결 오류:', error);
    res.status(500).send('서버 오류');
  } finally {
    // MongoDB 클라이언트 연결 종료
    await client.close();
  }
});

// 대시보드 페이지 (로그인 필요)
app.get('/dashboard', (req, res) => {
  if (req.session.user) {
    res.render('dashboard', { user: req.session.user }); // EJS 템플릿을 사용하여 dashboard.ejs 렌더링
  } else {
    res.redirect('/login');
  }
});

// HTTPS 서버 시작
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(PORT, () => {
  console.log(`HTTPS 서버가 ${PORT} 포트에서 실행 중입니다.`);
});

HTTPS으로 연결되는 것을 알 수 있다.

3.예외처리

1) HTTPS 설정 시 SSL/TLS 인증서 및 키만 등록할 경우에, app.js 서버는 HTTP로 실행되어 정상 동작하지 않음