라우터 분리 / 게시판 만들기

이지우·2024년 6월 27일
0

멋사

목록 보기
14/16

세션


세션을 생성하여 user객체를 가리키게 만들어 req, res는 garbage가 되지만 user객체(정보)는 그대로 남아있음
-> db 엑세스를 막고 메모리 엑세스를 사용하여 성능 향상

세션을 접근하기 위해서 세션id는 게속 유지시켜주어야함
-> 쿠키에 담아두고 그것을 db에 저장해둠

위는 모두 SSR 기반

  • p.545 전략 설정

  • b2b여서 client는 일반적인 사용자가 아니라 facebook-server(개발자)의 관계에서의 server(개발자)를 말함 (facebook이 server 역할)

  • p.557 serialize


라우터 분리

server.js에 mysql 연동되어 있고 account.js에서 mysql을 사용하려고 하면 server.js에서 account.js로 exports하고 다시 server.js로 라우터를 import해야됨
-> db를 따로 빼서 연결을 한번만 하자

const { MongoClient } = require('mongodb');
const mongoClient = require('mongodb').MongoClient;

node.js에서 MongoDB연동하여 게시판 만들기

const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = () => {
    const mongoDbUrl = `mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0`
    const mongoConn = MongoClient.connect(mongoDbUrl, 
        { 
            usenewUrlParser: true,
            useUnifiedTopology: true
        }); 

};
const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = async () => {
    const mongoDbUrl = `mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0`
    const mongoConn = await MongoClient.connect(mongoDbUrl, 
        { 
            usenewUrlParser: true,
            useUnifiedTopology: true
        }); 
	mongodb = mongoConn.db('myboard');
    console.log('몽고db 접속 성공');
};

mongoclient.connect는 비동기라 연결될때까지 기다리도록 추가


const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = async () => {
    const mongoDbUrl = `mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0`
    const mongoConn = await MongoClient.connect(mongoDbUrl, 
        { 
            usenewUrlParser: true,
            useUnifiedTopology: true
        }); 
    mongodb = mongoConn.db('myboard');
    console.log('몽고db 접속 성공');

    mysqldb = mysql.createConnection({
        host: 'localhost',
        user: 'jwbook',
        password: '1234',
        database: 'myboard'
    });
    
};

mysql.connect는 알아서 설정 안해도 완료될때까지 기다렸다가 실행됨 -> 동기


const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = async () => {
    if(mongodb && mysqldb){
        return { mongodb, mysqldb };
    }

    try{
        const mongoDbUrl = `mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0`
        const mongoConn = await MongoClient.connect(mongoDbUrl, 
            { 
                usenewUrlParser: true,
                useUnifiedTopology: true
            }); 
        mongodb = mongoConn.db('myboard');
        console.log('몽고db 접속 성공');

        mysqldb = mysql.createConnection({
            host: 'localhost',
            user: 'jwbook',
            password: '1234',
            database: 'myboard'
        });
        mysqldb.connect();
        console.log("MySQL 접속 성공");

        return { mongodb, mysqldb };
    }catch(err) {
        console.error("DB 접속 실패", err);
        throw err;	// 서버 가동 끝내게 만들기 위함
    }
};

mongodb와 mysqldb에 무언가 값이 있을 경우 (연결되었을 경우)와 없는 경우로 나누기


최종 db_setup.js

const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = async () => {
    if(mongodb && mysqldb){
        return { mongodb, mysqldb };
    }

    try{
        const mongoDbUrl = `mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0`
        const mongoConn = await MongoClient.connect(mongoDbUrl, 
            { 
                usenewUrlParser: true,
                useUnifiedTopology: true
            }); 
        mongodb = mongoConn.db('myboard');
        console.log('몽고db 접속 성공');

        mysqldb = mysql.createConnection({
            host: 'localhost',
            user: 'jwbook',
            password: '1234',
            database: 'myboard'
        });
        mysqldb.connect();
        console.log("MySQL 접속 성공");

        return { mongodb, mysqldb };
    }catch(err) {
        console.error("DB 접속 실패", err);
        throw err;
    }
};

module.exports = setup;

server.js

const setup = require("./db_setup");
const express = require("express");

const app = express();

app.listen(8080, () => {
    console.log("8080 서버가 준비되었습니다...");
});

const setup = require("./db_setup");
const express = require("express");

const app = express();

app.listen(8080, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

db구축을 위한 setup 호출
비동기라서 await


라우터 분리

routes 폴더에 account.js

const router = require('express').Router();

router.get('/', (req, res) => {
    res.send('홈');
});

const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', (req, res) => {
    setup();
    res.send('홈');
});

const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', (req, res) => {
    const { mongodb, mysqldb } = setup();
  // db_setup.js 의 return 값 받기
    res.send('홈');
});

const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', async (req, res) => {
    const { mongodb, mysqldb } = await setup();
  // db setup이 다 될때까지 기다려야해서 awit 추가
    res.send('홈 : db 사용 가능');
});

db setup이 다 될때까지 기다려야해서 awit 추가


const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', async (req, res) => {
  // db 연결 오류 처리 추가
    try{
        const { mongodb, mysqldb } = await setup();
        res.send('홈 : db 사용 가능');
    }catch(err){
        res.status(500).send('db fail');
    }
});

db 연결 오류 처리 추가


const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', async (req, res) => {
    console.log("GET / 처리 시작 ");
    try{
        const { mongodb, mysqldb } = await setup();
        res.send('홈 : db 사용 가능');
    }catch(err){
        res.status(500).send('db fail');
    }
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

router를 만들때마다 db 연결이 되지 않도록 하기위하여 하는 작업임 -> console.log로 확인가능


최종 account.js

const router = require('express').Router();
const setup = require('../db_setup');

router.get('/', async (req, res) => {
    try{
        const { mongodb, mysqldb } = await setup();
        res.send('홈 : db 사용 가능');
    }catch(err){
        res.status(500).send('db fail');
    }
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

server.js에 연결 추가

const setup = require("./db_setup");
const express = require("express");

const app = express();

//server.js에 연결 추가
app.use('/', require('./routes/account.js'));

app.listen(8080, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

account.js에서 server.js로 옮김

const setup = require("./db_setup");
const express = require("express");

const app = express();

app.get('/', async (req, res) => {
    console.log("GET / 처리 시작 ");
    try{
        const { mongodb, mysqldb } = await setup();
        res.send('홈 : db 사용 가능');
    }catch(err){
        res.status(500).send('db fail');
    }
});

app.use('/', require('./routes/account.js'));

app.listen(8080, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

index.ejs로 render하도록 수정

const setup = require("./db_setup");
const express = require("express");

const app = express();

app.get('/', (req, res) => {
    res.render('index.ejs');
});

app.use('/', require('./routes/account.js'));

app.listen(8080, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

account.js 수정

const router = require('express').Router();
const setup = require('../db_setup');

/////// 추가
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

회원가입

server.js에 bodyParser 추가

const setup = require("./db_setup");
const express = require("express");

const app = express();

const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
// 여러 개체 중복 가능

app.get('/', (req, res) => {
    res.render('index.ejs');
});

app.use('/', require('./routes/account.js'));

app.listen(8080, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

account.js에 추가

const router = require('express').Router();
const setup = require('../db_setup');

// 회원가입 화면 보기
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

// 회원가입 처리
router.post("/account/save", (req, res) => {
    console.log(req.body);
    res.send("save ok");
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

account.js

const router = require('express').Router();
const setup = require('../db_setup');

const sha = require('sha256');

// 회원가입 화면 보기
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

// 회원가입 처리
router.post("/account/save", async (req, res) => {
    //console.log(req.body);
    // db 객체가 있어야 저장
    const { mongodb, mysqldb } = await setup();    // 비동기
    
    res.send("save ok");
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

const router = require('express').Router();
const setup = require('../db_setup');

const sha = require('sha256');

// 회원가입 화면 보기
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

// 회원가입 처리
router.post("/account/save", async (req, res) => {
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({userid: req.body.userid})
        .then(result => {
            if(result){// 중복 상태
                res.render('enter.ejs', {data: {msg: 'ID가 중복되었습니다.'}});
            } else {
                const generateSalt = (length = 16) => {
                    const crypto = require('crypto');
                    return crypto.randomBytes(length).toString('hex');  // 버퍼를 16진수의 string으로 바꿔 반환
                };
            }
        })
        .catch();
    res.send("save ok");
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

id가 db에 있는지에 따라 작업 설정


const router = require('express').Router();
const setup = require('../db_setup');

const sha = require('sha256');

// 회원가입 화면 보기
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

// 회원가입 처리
router.post("/account/save", async (req, res) => {
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({userid: req.body.userid})
        .then(result => {
            if(result){// 중복 상태
                res.render('enter.ejs', {data: {msg: 'ID가 중복되었습니다.'}});
            } else {
                const generateSalt = (length = 16) => {
                    const crypto = require('crypto');
                    return crypto.randomBytes(length).toString('hex');  // 버퍼를 16진수의 string으로 바꿔 반환
                };

                const salt = generateSalt();
                console.log(req.body);
                req.body.userpw = sha(req.body.userpw + salt);
                mongodb.collection('account')
                    .insertOne()
                    .then()
                    .catch();
            }
        })
        .catch();
    res.send("save ok");
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

아래처럼 추가

const salt = generateSalt();
                console.log(req.body);
                req.body.userpw = sha(req.body.userpw + salt);
                mongodb.collection('account')
                    .insertOne(req.body)
                    .then( result => {
                        if(result){
                            console.log('회원가입 성공');
                            mysqldb.query(sql, [], ()=>{{}})
                        }
                    })
                    .catch();

mysql에 salt 저장

const salt = generateSalt();
console.log(req.body);
req.body.userpw = sha(req.body.userpw + salt);
mongodb.collection('account')
    .insertOne()
    .then( result => {
        if(result){
            console.log('회원가입 성공');
            const sql = `insert into usersalt(userid, salt) values (?, ?)`
            mysqldb.query(sql, [req.body.userid, salt], (err, rows, fields)=>{
                if (err){
                    console.log(err);
                } else {
                    console.log('salt 저장 성공');
                }
            });
            res.redirect('/');
        } else{
            console.log('회원가입 fail');
            res.render('enter.ejs', {data: {alertMsg: '회원가입 실패'}});    // 페이지 그대로 머무는것 처럼 보이게
        }
    })
    .catch();

(ID 중복확인 후 비밀번호 암호화)

const router = require('express').Router();
const setup = require('../db_setup');

const sha = require('sha256');

// 회원가입 화면 보기
router.get('/account/enter', (req, res) => {
    res.render('enter.ejs');
});

// 회원가입 처리
router.post("/account/save", async (req, res) => {
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({userid: req.body.userid})
        .then(result => {
            if(result){// 중복 상태
                res.render('enter.ejs', {data: {msg: 'ID가 중복되었습니다.'}});
            } else {
                const generateSalt = (length = 16) => {
                    const crypto = require('crypto');
                    return crypto.randomBytes(length).toString('hex');  // 버퍼를 16진수의 string으로 바꿔 반환
                };

                const salt = generateSalt();
                console.log(req.body);
                req.body.userpw = sha(req.body.userpw + salt);
                mongodb.collection('account')
                    .insertOne(req.body)
                    .then( result => {
                        if(result){
                            console.log('회원가입 성공');
                            const sql = `insert into usersalt(userid, salt) values (?, ?)`
                            mysqldb.query(sql, [req.body.userid, salt], (err, rows, fields)=>{
                                if (err){
                                    console.log(err);
                                } else {
                                    console.log('salt 저장 성공');
                                }
                            });
                            res.redirect('/');
                        } else{
                            console.log('회원가입 fail');
                            res.render('enter.ejs', {data: {alertMsg: '회원가입 실패'}});    // 페이지 그대로 머무는것 처럼 보이게
                        }
                    })
                    .catch(err => {
                        console.log(err);
                        res.status(500).send(); 
                    });
            }
        })
        .catch(err => {
            console.log(err);
            res.status(500).send(); 
        });
});

router.get('/login', async (req, res) => {
    console.log("GET /login 처리 시작 ");
    try {
        const { mongodb, mysqldb } = await setup();
        res.send("홈화면 : 데이터베이스 사용 가능");
    } catch (err) {
        res.status(500).send("데이터베이스 연결 실패");
    }
});

module.exports = router;

enter.ejs

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Home</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    </head>
    <body>
        <%- include('menu.html') %>
    
        <% if(typeof data != 'undefined' && data.alertMsg){ %>
            <script>
                alert(`<%= data.alertMsg %>`);
            </script>
        <% } %>

        <div class = "container mt-4">
            <h1>회원가입</h1>
            <form action = "/account/save" method="post">
                <div class = "form-group">
                <label>아이디</label>
                <input type="text" name = "userid" class = "form-control">
                <% if (typeof data != 'undefined' && data.msg){ %>
                    <span class = 'text-danger'><%= data.msg %></span>
                <% } %>
                </div><p></p>
                
                <div class="form-group">
                <label>비밀번호</label>
                <input type="password"  class="form-control" name ="userpw">
                </div><p></p>  
                
                <div class="form-group">
                <label>이름</label>
                <input type="text"  class="form-control" name ="username">
                </div><p></p> 

                <button type = "submit" class="btn btn-warning" style="float:right">회원가입</button>
            </form>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
    </body>
</html>

환경변수

npm i dotenv

db_setup.js 맨 위에 추가

const dotenv = require('dotenv').config();

.env 파일 생성

MONGODB_URL = 'mongodb+srv://admin:1234@cluster0.gnyth4u.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0'
MONGODB_DB = 'myboard'

MYSQL_HOST = 'localhost'
MYSQL_USER = 'jwbook'
MYSQL_PASSWORD = '1234'
MYSQL_DB = 'myboard'

db_setup.js에 수정

const dotenv = require('dotenv').config();
const { MongoClient } = require('mongodb');
const mysql = require('mysql');

let mongodb;
let mysqldb;

const setup = async () => {
    if(mongodb && mysqldb){
        return { mongodb, mysqldb };
    }

    try{
        const mongoDbUrl = process.env.MONGODB_URL;
        const mongoConn = await MongoClient.connect(mongoDbUrl, 
            { 
                usenewUrlParser: true,
                useUnifiedTopology: true
            }); 
        mongodb = mongoConn.db(process.env.MONGODB_DB);
        console.log('몽고db 접속 성공');

        mysqldb = mysql.createConnection({
            host: process.env.MYSQL_HOST,
            user: process.env.MYSQL_USER,
            password: process.env.MYSQL_PASSWORD,
            database: process.env.MYSQL_DB
        });
        mysqldb.connect();
        console.log("MySQL 접속 성공");

        return { mongodb, mysqldb };
    }catch(err) {
        console.error("DB 접속 실패", err);
        throw err;
    }
};

module.exports = setup;

로그인 처리

menu.html

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">


<nav class="navbar navbar-expand-lg bg-info">
    <div class="container-fluid">
      <!--  ///////// 추가 ///////   -->
        <span id="loginSpan">
            <form action="/account/login" method="post">
                ID <input size="3" name="userid"> 
                PW <input size="3" name="userpw"> 
                <input type="submit" value="login" class="btn btn-outline-warning">
            </form>
        </span>
      <!--     ///////////////  -->
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="/">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/post/list">게시글목록</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/account/enter">회원가입</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled">Disabled</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

nav bar에 로그인 추가


account.js에서 post방식으로 수정 후 데이터 넘어오는지 확인

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
});

로그인 되면 다시 index 페이지로 이동하게 만들기

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    // login ok 경우
    res.render('index.ejs');
});

index.ejs는 menu.html을 include하고 있음
menu.html에 script 추가

<script>
    alert();
</script>

이렇게 script를 추가해두면 nav bar가 포함된 어떤 페이지를 들어가도 이게 선행되어 수행됨
본문을 랜더링하기 전에 먼저 수행

메뉴가 있을때마다 웹브라우저 메모리에 쿠키 확인
쿠키가 있으면 로그아웃 버튼 보이게

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<script>
    // 웹 브라우저 메모리에 uid 쿠키가 있는지 확인
    if(uid){
        $('#loginSpan').html(`<button>logout</button>`); // 로그아웃 버튼
    }
    
</script>

cookie 값 가져오기 위한 jquery 추가

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>

<script>
    // 웹 브라우저 메모리에 uid 쿠키가 있는지 확인
    const uid = $.cookie('uid');    // 없으면 null로 들어감
    if(uid){
        $('#loginSpan').html(`<button>logout</button>`);
    }
    
</script>

직접 쿠키 추가하면 logout으로 바뀜

버튼 앞에 아이디 추가

<script>
    // 웹 브라우저 메모리에 uid 쿠키가 있는지 확인
    const uid = $.cookie('uid');    // 없으면 null로 들어감
    if(uid){
        $('#loginSpan').html(`${uid} <button>logout</button>`);
    }
</script>


<script>
    // 웹 브라우저 메모리에 uid 쿠키가 있는지 확인
    const uid = $.cookie('uid');    // 없으면 null로 들어감
    if(uid){
        $('#loginSpan').html(`${uid} <button onclick = 'logout()'>logout</button>`);
    }
    
    function logout(){
        $.removeCookie('uid', { path: '/' });
        location.reload();
    }
</script>

logout 버튼 클릭 시 cookie가 삭제됨
다시 login 입력이 보이게됨


클라이언트에서만 reload하면 서버쪽에서 세션30분이 그대로 남겨짐

<script>
    // 웹 브라우저 메모리에 uid 쿠키가 있는지 확인
    const uid = $.cookie('uid');    // 없으면 null로 들어감
    if(uid){
        $('#loginSpan').html(`${uid} <button onclick = 'logout()'>logout</button>`);
    }
    
    function logout(){
        $.removeCookie('uid', { path: '/' });
        location.href = '/account/logout';
    }
</script>

서버쪽에 보내지도록 href로 작성
account.js에 라우터 추가

router.get('/account/logout', (req, res) => {
    req.session.destroy();
});

herf는 다 get방식으로 넘어옴


session 사용을 위해 모듈 설치

npm i express-session cookie-parser

server.js에 session과 cookie 설정

const setup = require("./db_setup");
const express = require("express");

const session = require("express-session");
app.use(
    session({
        secret: "암호화키",
        resave: false,
        saveUninitialized: false,
    })
);

const cookieParser = require("cookie-parser");
app.use(cookieParser());

const app = express();

const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));

app.get('/', (req, res) => {
    res.render('index.ejs');
});

app.use('/', require('./routes/account.js'));

app.listen(process.env.WEB_PORT, async () => {
    await setup();
    console.log("8080 서버가 준비되었습니다...");
});

account.js에서 로그인 처리부분 설정

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], () => {});
            } else {

            }
        })
        .catch();
    
});

mysql에서 가져온 usersalt와 password 합쳐서 암호화

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                });
            } else {

            }
        })
        .catch();
    
});

로그인 성공/실패 작업 추가

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                    if(result.userpw == hashPw){
                        // login ok
                        res.render('index.ejs');
                    } else {
                        // pw fail
                        res.render('login.ejs');
                    }
                });
            } else {

            }
        })
        .catch();
    
});

세션, 쿠키 추가

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                    if(result.userpw == hashPw){
                        // login ok
                        req.session.user = req.body;
                        res.cookie('uid', req.body.userid);
                        res.render('index.ejs');
                    } else {
                        // pw fail
                        res.render('login.ejs');
                    }
                });
            } else {

            }
        })
        .catch();
    
});

세션에 req.body를 넣을 때 비밀번호가 평서문으로 작성되어 있으므로 해시로 변경

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                    if(result.userpw == hashPw){
                        // login ok
                        req.body.userpw = hashPw;
                        req.session.user = req.body;
                        res.cookie('uid', req.body.userid);
                        res.render('index.ejs');
                    } else {
                        // pw fail
                        res.render('login.ejs');
                    }
                });
            } else {

            }
        })
        .catch();
    
});

오류처리

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                    if(result.userpw == hashPw){
                        // login ok
                        req.body.userpw = hashPw;
                        req.session.user = req.body;
                        res.cookie('uid', req.body.userid);
                        res.render('index.ejs');
                    } else {
                        // pw fail
                        res.render('login.ejs');
                    }
                });
            } else {
                // login fail
                res.render('login.ejs');
            }
        })
        .catch(err => {
            // login fail
            res.render('login.ejs');
        });
    
});

session 처리가 완료되었으니 logout시에 삭제 후 index.ejs로 foward

router.get('/account/logout', (req, res) => {
    req.session.destroy();
    res.render('index.ejs');
})

로그인 실패 시 alert이 뜨도록 수정

// 로그인 처리
router.post('/account/login', async (req, res) => {
    console.log(req.body);
    // db연결
    const { mongodb, mysqldb } = await setup();
    mongodb.collection('account')
        .findOne({ userid: req.body.userid })
        .then(result => {
            if (result) {
                const sql = `SELECT salt FROM UserSalt 
                            WHERE userid=?`
                mysqldb.query(sql, [req.body.userid], (err, rows, fields) => {
                    const salt = rows[0].salt;
                    const hashPw = sha(req.body.userpw + salt);
                    if(result.userpw == hashPw){
                        // login ok
                        req.body.userpw = hashPw;
                        req.session.user = req.body;
                        res.cookie('uid', req.body.userid);
                        res.render('index.ejs');
                    } else {
                        // pw fail
                        res.render('login.ejs', {data: {alertMsg: '다시 로그인 해주세요'}});
                    }
                });
            } else {
                // login fail
                res.render("index.ejs", {data:{alertMsg:'다시 로그인 해주세요'}});
            }
        })
        .catch(err => {
            // login fail
            res.render("index.ejs", {data:{alertMsg:'다시 로그인 해주세요'}});
        });
    
});

inde.ejs에 alertMsg가 전달되었을 때 추가
bootstrap 추가하는 href와 script는 menu.html에 넣어놔서 지우기

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Home</title>
    </head>
    <body>
        <%- include('menu.html') %>

        <% if(typeof data != 'undefined' && data.alertMsg){ %>
            <script>
                alert(`<%= data.alertMsg %>`) ;
            </script>            
        <% } %>
        
        <h1>홈입니다.</h1>
    
    </body>
</html>
profile
노력형 인간

0개의 댓글