클라우드 12일차

soso·2024년 6월 25일

클라우드 부트캠프

목록 보기
14/77

세션

세션 동작 원리

1. 서버와 서블릿 가동

  • 서버가 가동될 때 서블릿 객체가 일반 메모리 영역에 하나 생성

  • 이 서블릿 객체는 상속되는 모든 데이터도 함께 생성하며, application scope에 속함

  • 서버 가동 시 객체가 하나 생성되고, 이는 param 테이블과 attribute 테이블 등의 정보를 포함

2. 사용자 요청 처리

  • 사용자가 웹 서버에 index.html을 요청하고 로그인 정보를 입력하여 request를 보낼 시

  • 최초 request는 쿠키가 없고 POST 방식으로 id와 pw가 전송되어 서블릿에 도착

  • 요청은 request queue에 쌓이고 request 객체가 생성(각 객체는 동일한 우선순위를 가짐)

3. 스택과 스레드 처리

  • 작업이 시작되면 메모리의 스택 영역의 메인 스택에 request와 response 객체의 주소가 가리켜짐

  • 스레드는 스택 영역 내에서 작업을 수행하며, 다른 스레드가 CPU 사용 권한을 소모하면 대기 상태로 넘어감

  • 이 과정은 반복되며 여러 스레드가 순차적으로 작업을 수행

4. DB 확인 및 세션 생성

  • request 정보는 DB에 가서 확인 작업을 수행

  • 확인이 완료되면 user 객체가 생성, 이 객체는 회원 정보를 포함

  • 세션을 사용하여 이 객체를 저장

5. 세션 관리

  • req.session을 통해 세션이 할당, 세션은 테이블 형태로 값을 저장

  • 쿠키가 생성되고, response 헤더에 포함되어 응답

  • 커넥션이 종료되어 스택영역이 삭제된 후 쿠키가 삭제되어도 세션에 남아있는 user 정보는 세션 유지 시간(기본 30분) 동안 유지

saveUninitialized

express-session

  • express-session은 서버가 세션을 이용하게 해 주고 사용자 쿠키에 세션 정보를 담을 수 있게 하는 미들웨어

  • 사용자 쿠키에 세션 데이터를 담을 때는 세션의 모든 데이터를 담는 것이 아니라 세션의 id값을 저장하고 서버에서 데이터를 관리하게 함

express-session 미들웨어를 사용하는 형태

let session = require('express-session');
app.use(session({
  secret : '암호키',			//세션 아이디를 암호화하기 위한 재료 값
  resave : false,			//세션을 접속할 때마다 새로운 세션 식별자(sid)의 발급 여부를 결정
  							//일반적으로는 false로 설정
  saveUninitialized : false
}));

세션이 생성되었지만 어떠한 데이터도 추가되거나 변경되지 않은 상태를 uninitialized라고 함

  • saveUninitialized : true

    • uninitialized session도 저장, 사용자가 아무런 작업을 하지 않아도 세션이 생성되어 저장
  • saveUninitialized : false

    • uninitialized session은 저장하지 않음, 사용자가 세션에 데이터를 저장할 때만 세션이 저장

saveUninitialized : true로 설정하면 개발자 도구에서 세션ID(SID)를 삭제해도 새로고침할 때마다 새로운 세션이 생성되어 서버 메모리를 많이 차지해 과부하 되는 문제 발생

이를 방지하기 위해 saveUninitialized : false로 설정하여 필요하지 않은 세션이 서버에 저장되지 않도록 함

클라이언트 측 렌더링(CSR)을 위한 uid 활용

모든 요청에 대해 서버 측 렌더링(SSR)을 수행하면 서버에 과부하가 발생할 수 있음, 이를 해결하기 위해 CSR을 사용

CSR을 사용하기 위해서는 서버에서 전달받은 데이터로 클라이언트에서 페이지를 렌더링하는데, 이 과정에서 세션 정보를 이용

세션 관리

  • sid(session ID)

    • 일반적으로 세션을 관리하기 위해 사용

    • sid는 서버에서 생성되어 클라이언트의 쿠키에 저장되고, 이후 요청 시 이 쿠키를 통해 세션을 식별

  • uid(user ID)

    • 사용자 식별을 위한 ID, 보안 쿠키(httpOnly)로 설정됨

    • httpOnly로 설정된 쿠키는 클라이언트 측에서 바닐라 JavaScript로 접근할 수 없음

uid 쿠키를 httpOnly 속성 없이 설정하여 클라이언트 측에서 uid를 이용해 사용자 정보를 처리하게 해 CSR 수행

로그인

app.get('/login', function (req, res) {
  if (req.session.user) {									//req.session.user에 사용자의 세션이 이미 등록되어 있다면
    res.render('index.ejs', { user: req.session.user });	//홈 화면인 index.ejs에 {user:req.session.user} 데이터를 넘겨주며 이동
  } else {
    res.render('login.ejs');
  }
});

app.post('/login', function (req, res) {
  console.log("아이디 : " + req.body.userid);
  console.log("비밀번호 : " + req.body.userpw);
  mydb
    .collection('account')
    .findOne({ userid: req.body.userid })
    .then(result => {
      if (result != null && result.userpw == req.body.userpw) {
        req.session.user = req.body;
        console.log('새로운 로그인');
        res.render('index.ejs', { user: req.session.user });//처음 로그인 시에 로그인에 성공하면
        													//홈 화면인 index.ejs로 {user:req.session.user} 데이터를 넘겨주며 이동
      } else {
        res.render('login.ejs', { user: null });			//로그인에 실패했다면 login.ejs로 이동
      }
    });
});

로그아웃

app.get('/logout', (req, res) => {
  console.log('로그아웃');
  req.session.destroy();					//req.session.destroy() 함수를 호출하면 현재 도메인의 세션을 삭제
  res.render('index.ejs', { user: null });
});

회원가입

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

app.post('/signup', (req, res) => {
  console.log(req.body);
  console.log(req.body.userpw);
  mydb.collection('account')
    .insertOne({
      userid: req.body.userid,
      userpw: req.body.userpw,
      usergroup: req.body.usergroup,
      useremail: req.body.useremail
    })
    .then(result => {
      console.log('회원가입 성공');
    })
    .catch(err => {
      console.log(err);
    });
  res.redirect('/');
});

암호화

가입 시 비밀번호 암호화

암호화

  • 평문(plain text)을 암호문(crypto text)으로 변환하는 과정

  • 사용자가 입력한 데이터를 알아볼 수 없는 데이터로 변경하여 외부로부터 데이터를 보호

  • 암호화를 했다면 암호문을 다시 평문으로 변환할 수 있어야 하는데 이러한 과정을 복호화라고 함

단방향 암호화

  • 암호화를 수행한 데이터를 다시 원래의 데이터로 되돌릴 수 없는 방식(복호화 불가)

양방향 암호화

  • 암호화를 수행한 데이터를 다시 원래의 데이터로 되돌릴 수 있는 방식(복호화 가능)

밑의 코드들에서는 단방향 암호화 기법인 SHA256을 이용

npm install sha256

const sha = require('sha256');
app.post('/signup', (req, res) => {
  console.log(req.body);
  console.log(sha(req.body.userpw));
  mydb.collection('account')
    .insertOne({
      userid: req.body.userid,
      userpw: sha(req.body.userpw),
      usergroup: req.body.usergroup,
      useremail: req.body.useremail
    })
    .then(result => {
      console.log('회원가입 성공');
    })
    .catch(err => {
      console.log(err);
    });
  res.redirect('/');
});

비밀번호 암호화 시 로그인

이미 암호화된 DB의 비밀번호를 복호화할 수 없기에 반대로 사용자가 입력한 비밀번호를 암호화하여 비교한 후 로그인

app.post('/login', function (req, res) {
  console.log("아이디 : " + req.body.userid);
  console.log("비밀번호 : " + req.body.userpw);
  mydb
    .collection('account')
    .findOne({ userid: req.body.userid })
    .then(result => {
      if (result != null && result.userpw == sha(req.body.userpw)) {
        req.session.user = req.body;
        console.log('새로운 로그인');
        res.render('index.ejs', { user: req.session.user });
      } else {
        res.render('login.ejs');
      }
    });
});

https://rattle-coal-060.notion.site/f7bc264fa0b84632b0033645237fc102 내용 추가하기

0개의 댓글