MapleStory Finger Point
본문 바로가기
Back-end/Node.js - Express

[Express] 로그인 구현 (express-session 를 통한 세션작업 연습)

by 디팔⸜( ◜࿁◝ )⸝︎︎ 2022. 10. 23.
const express = require("express");
const cors = require("cors");
const mysql = require("mysql");
const { query } = require("express");
const session = require('express-session');
// npm install express-session으로 설치해줌.
const app = express();
const port = 3000;

 

  • express-session 을 사용하기 위해 npm install express-session 명령어를 통해 설치해주었다.

app.use(cors(
    { "origin" : "http://localhost:8081", 
      credentials : true }
    ));

 

  • 인증되지 않은 로컬 파일(front에 해당하는 html 파일을)과의 통신을 위해, 해당 front 파일을
    http-server를 통해 서버에 올려주었다. (이는 brew install http-server로 설치할 수 있다 M1 기준)
    credential 속성이 세션, 쿠키를 생성하고 주고받는 데 필요한 속성이다.

const conn = mysql.createConnection({
    host: "localhost",
    port: 3306,
    user: "*",
    password: "*",
    database: "*",
});

 

  • database 연결을 위한 코드이다.

conn.connect((error) => {
    if (error) {
    console.log("database disconnected", error);
    } else {
    console.log("database connected");
    }
});

function _callQuery(query, values, res){
    // 중복되는 부분을 함수화하기 위함, 아래 실제로 실행되는 코드에서 각 query, values, res를 받고 
	// 있으므로 매개변수로 설정해준다.
    conn.query(query, values, (error, rows) => {
        let code, status, result;
        if(error) {
            res.send("error ! :" + error.message);
            code = 400;
            status = "failed";
            result = error.message;
            // 에러가 발생하면 error.message와 code, status, result의 값을 
            // 코드 맨 아래 값에 전달한다.
        } else {
            code = 200;
            status = "succeed"
            result = rows;
            // 성공적으로 수행되면 해당 값을 마지막 코드의 인수로 전달한다.
        }
        res.send({ "code": code, "status": status, "result" : result })
    });
}

function _authCheck(req, res, next){
    // 인증 (authorized) 확인을 위한 함수로, 만약 인증되지 않았을 경우 
    // 401 코드 (unAuthorized)를 뿜고 그게 아니라면, 다음 수행될 함수를 실행한다.
    if(!req.session.user){
        res.send({ "code": 401, "status": "failed", "result": "unauthorized"});
    } else {
    next();
    // 에러가 발생하지 않으면 다음 함수가 실행된다.
    }
}

app.get("/user", _authCheck, (req, res)=> {
    const query = "select id, name from userInpo";
    _callQuery(query, [], res);
    // 반복되는 부분은 함수화하여 처리해주었다.
    }
);

app.get("/user/:id", _authCheck, (req, res)=> {
    const id = req.params.id;
    const query = "select id, name from userInpo where id = ?";
    const values = [ id ]
    _callQuery(query, values, res);
});

 

  • get 요청에 따른 유저정보 반환과 id별 유저정보 반환을 수행하는 코드이다.

 

  • 쿼리에 값을 담아보낼 때, 위와 같이 ?를 사용하는 경우가 있다.
    이런 경우에 values를 선언하고 이에 ?에 담길 값을 입력해주어야 한다. 이를 'prepared statement' 라고 한다.
    이는 SQL Injection 공격을 막는 방법으로, 이와 같이 선언할 경우
    DBMS에서 해당 쿼리에 담는 value값이 또 다른 쿼리를 포함하지 않는지 검증하는 단계를 거친다.
    SQL Injection이란 추후에 더 다루어보겠다.

app.post("/user", (req, res)=> {
    // 회원가입을 수행하는 코드로, 이는 인증받지 않은 대상도 접근 가능해야하기에 _authCheck 함수가 포함되지 않았다.
    const id = req.body.id;
    const name = req.body.name;
    const password  = req.body.password
    const query = "insert into userInpo (id, name, password) values (?, ?, ?)";
    const values = [ id, name, password ];
    _callQuery(query, values, res);
});

app.put("/user", _authCheck, (req, res)=> {
    const id = req.body.id;
    const name = req.body.name;
    const password  = req.body.password
    const query = "update userInpo set name = ?, password = ? where id = ?";
    const values = [ name, password, id ];
    _callQuery(query, values, res);
});

app.delete("/user", _authCheck, (req, res)=> {
    const id = req.body.id;
    const query = "delete from userInpo where id = ?";
    const values = [ id ];
    _callQuery(query, values, res);
});

 

  • 각 회원가입, 수정, 삭제를 수행하는 코드이다.

app.post("/login", (req, res) =>{
    const id = req.body.id;
    const password = req.body.password;
    const query = "select * from userInpo where id = ? and password = ?";
    const values = [ id, password ];
    conn.query(query, values, (error, rows) => {
        let code, status, result;
        if(error) {
            res.send("error ! :" + error.message);
            code = 400;
            status = "failed";
            result = error.message;
        } else {
            code = 200;
            status = "succeed"
            result = rows;
            // TODO : 로그인 처리하기
            if(rows[0]){
            let user = {};
            user.id = rows[0].id;
            user.name = rows[0].name;
            req.session.user = user;
            } else {
                code = 401;
                status = "failed";
                result = "로그인 정보를 확인하세요.";
            }
        }
        res.send({ "code": code, "status": status, "result" : result })
    });
})

 

  • 로그인 작업 시 수행되는 코드이다.
  • TODO : 로그인 처리하기 아래 코드부터 
    세션에 해당 유저의 id와 name을 저장하고, 이를 바탕으로 쿠키를 전달하게 된다.

*개인적으로 이해한 바를 적은 것이라

잘못된 부분이 있을 수 있습니다. 혹시 잘못된 부분이 있다면 댓글로 알려주시면 정정하겠습니다.*

 

*참고하면 좋을 것 같은 글

 

[Nodejs] [Express] 세션(Session) 사용하기

1. 세션이란? 앞서 설명했던 쿠키는 웹 브라우저에 저장되는 '키-밸류' 타입의 데이터라고 언급...

blog.naver.com

 

댓글