728x90
반응형

회사에서 사용자들 수에 대한 제한을 두어서 중복 로그인 방지를 구현하게 되었다.

쿠키는 브라우저에만 남기에 중복 로그인을 쿠키로만으로는 구현할 수 없다.

 

세션은 데이터베이스에 저장이 되기 때문에 많은 정보를 담으면 서버에 과부하가 올 수 있다. 때문에 길이가 긴 데이터들은 jwt를 이용하였고, 키 값인 아이디만 세션에 두고 로그인 중인 사용자가 있으면 중복 로그인을 방지하게끔 구현했다. 

 

1. 세션 관련 모듈을 설치한다.

$npm i express-session --save
$npm i express-mysql-session -- save

 

2. app.js에 다음과 같이 추가해준다.

 ... 
var session = require('express-session');
var MySQLStore = require('express-mysql-session')(session);

 ...

var option = {
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PW,
    port: process.env.DB_PORT,
    database: process.env.DB_DATABASE,
    clearExpired: true,
    checkExpirationInterval: 10000,
    expiration: 10000
}

var sessionStore = new MySQLStore(option);

app.use(session({
  secret: process.env.secret,
  resave: false,
  saveUninitialized: true,
  store: sessionStore
  
}))

option 중 세션에 관한 내용을 살펴보면,

  • clearExpired : 유효기간이 지난 세션을 삭제한다.
  • checkExpirationInterval : 세션의 유효기간을 체크하는 시간을 설정한다.
  • expiration : 세션의 유효기간을 설정한다.

 

3. 라우터에서의 사용법은 다음과 같다.

router.get("/", function (req, res, next) {
  
  req.session.uid = "uid" // 세션 생성
  delete req.session.uid // 세션 삭제
  
  res.send({success : true })
});

 

보통은 로그인을 한 정보를 쿠키에 담는다. 그 후에 로그인 정보가 쿠키에 있으면 별도의 로그인 화면 없이 바로 메인 화면으로 가게끔 편의성을 위해 구현해둔 경우도 있다.

 

먼저 우리는 로그인을 할 때 쿠키에 로그인 정보를 담기 이전에 세션에 이미 로그인 중인 데이터가 있는지 확인할 것이다.

그리고 데이터가 없으면 쿠키에 로그인 정보를 담고 로그인에 성공한다.

 

세션이 생기는 경로는 로그인밖에 없지만 세션이 삭제되어야하는 경우는 두 가지가 있다.

  1. 로그아웃을 해서 세션을 삭제
  2. 세션의 expiration 시간이 지나면 자동으로 삭제

이미 위에서 세션의 유효시간을 설정했기 때문에 두 번째의 경우는 설정이 따로 필요없다. 하지만 로그아웃 버튼을 클릭했을 때는 우리가 직접 쿼리로 삭제해주어야 한다.

 

그러기 위해 먼저 sequelize model에 sessions 파일을 추가해준다. sequelize에 대한 내용은 다음 포스트를 참고하자.

 

https://typo.tistory.com/entry/MySQL-CRUD-with-Reactjs-and-Nodejs-Back-End1?category=905676

 

MySQL | CRUD with Node.js | Sequelize

Server.js 먼저 백엔드 서버를 express로 실행하기위해 설치해준다. $ npm install express 그다음 package.json에 스크립트 서버를 실행하는 명령어를 추가해준다. server/package.json { "scripts": { "start":..

typo.tistory.com

 

sequelize/models/sessions.js 

module.exports = (sequelize, DataTypes) => {

    const Sessions = sequelize.define("Sessions", {
        session_id: {
            type: DataTypes.STRING,
            primaryKey: true,
        },
        expires: {
            type: DataTypes.STRING
        },
        data: {
            type: DataTypes.STRING
        },
    }, {
        charset: "utf8", // 한국어 설정
        collate: "utf8_general_ci", // 한국어 설정
        tableName: "sessions", // 테이블 이름
        timestamps: false, // createAt & updateAt 활성화
    });
    return Sessions;
};

 

4. 로그인과 로그아웃을 구성해준다.

const { QueryTypes, sequelize } = require('sequelize');
const db = require('../sequelize/models');


router.get("/login", function (req, res, next) {

	// 로그인 정보가 있는지 확인 
    
    	...
        
	// 세션이 존재하는지 확인
    const select_data_query = `SELECT JSON_EXTRACT(data, '$.uid') as uid FROM SESSIONS WHERE JSON_EXTRACT(data, '$.uid') = :uid`

          db.sequelize.query(
            select_data_query,
            {
              replacements: { uid: "teepo" },
              type: QueryTypes.SELECT
            }
          ).then((result) => {
            // 세션이 존재하지 않을 경우
            if(result.length === 0) {
            
                // 세션 생성
                req.session.uid = "teepo"
                
                // jwt 토큰 사용자면 jwt 토큰 생성
                
                // 쿠키 생성
                res.cookie('isLogined', {"uid": "teepo"}, { maxAge: 86400000, path: "/", httpOnly: true });
                
                res.send({success : true})
            }
            // 세션이 존재할 경우
            else {
            	return res.send({success : false, result : "이미 접속중인 사용자입니다."})
                }
          })
});

router.get("/logout", function (req, res, next) {
  
  // 세션에 존재하는 uid 데이터와 일치하는 데이터 삭제
  const delete_data_query = `DELETE FROM SESSIONS WHERE JSON_EXTRACT(data, '$.uid') = :uid`

  db.sequelize.query(
    delete_data_query,
    {
      replacements: { uid: req.session.uid },
      type: QueryTypes.DELETE
    }
  ).then((result) => {

    // 세션 삭제
    delete req.session.uid;

    // 쿠키 삭제
    res.clearCookie('isLogined');

    res.send({ success: true }); // 클라이언트에 결과 반환

  }).catch((err) => {
    console.log(err)
  })
});

 

728x90
반응형

'DB > MySQL' 카테고리의 다른 글

MySQL | Connection 문제 해결  (0) 2021.12.21
MySOL | MariaDB timeout 설정  (0) 2021.12.20
MySQL | CRUD with Node.js | Update and Delete  (0) 2021.12.09
MySQL | CRUD with Node.js | Find  (0) 2021.12.08
MySQL | CRUD with Node.js | Create  (0) 2021.12.08

+ Recent posts