ABOUT ME

Today
Yesterday
Total
  • 노드 세션 사용하기
    노드 2023. 4. 13. 16:36

    쿠키의 정보는 노출되고 수정되는 위험이 있다. 해결방법은 다음과 같다

    • 중요한 정보는 서버에서 관리하고 클라이언트에는 세션 키만 제공
    • 서버에 세션 객체(session) 생성 후, uniqueInt(키)를 만들어 속성명으로 사용
    • 속성 값에 정보를 저장하고 uniqueInt를 클라이언트에 보냄
    //session.js
    const http = require('http');
    const fs = require('fs').promises;
    const url = require('url');
    const qs = require('querystring');
    
    const parseCookies = (cookie = '') =>
      cookie
        .split(';')
        .map(v => v.split('='))
        .reduce((acc, [k, v]) => {
          acc[k.trim()] = decodeURIComponent(v);
          return acc;
        }, {});
    
    const session = {};
    
    http.createServer(async (req, res) => {
      const cookies = parseCookies(req.headers.cookie);
      if (req.url.startsWith('/login')) {
        const { query } = url.parse(req.url);
        const { name } = qs.parse(query);
        const expires = new Date();
        expires.setMinutes(expires.getMinutes() + 5);
        const uniqueInt = Date.now();
        session[uniqueInt] = {
          name,
          expires,
        };
        res.writeHead(302, {
          Location: '/',
          'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
        });
        res.end();
      // 세션쿠키가 존재하고, 만료 기간이 지나지 않았다면
      } else if (cookies.session && session[cookies.session].expires > new Date()) {
        res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
        res.end(`${session[cookies.session].name}님 안녕하세요`);
      } else {
        try {
          const data = await fs.readFile('./cookie2.html');
          res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
          res.end(data);
        } catch (err) {
          res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end(err.message);
        }
      }
    })
      .listen(8085, () => {
        console.log('8085번 포트에서 서버 대기 중입니다!');
      });

    서버 쪽에서 데이터를 저장할 seeson 객체를 만들었다. 그리고 쿠키 포스팅했을 때와 다 같은데 

    const uniqueInt = Date.now(); 이 부분부터 달라진다. 

    uniqueInt라는 키를 만들었고 현재 시간을 거기에 할당했다. 

    다음에 만든 session 객체에 uniqueInt 를 키로하는 값 name, expires를 할당했다.  

    이때 브라우저에는 name이나 expires를 보내는게 아니라 uniqueInt를 보낸다. 고유한 키 값만 보내는 것이다. 

    쿠키와는 다르게 쿠키의 값이 168137...로 표시가 되는 것을 볼 수 있다. 따라서해커들이 봤을때 어떤 값을 쓰고 있는지 모를 가능성이 높다. (보안성이 훨씬 좋다)

     

    그리고 세션 쿠키가 존재하고, 만료 기간이 지나지 않았다면 다음번 호출때는

    else if (cookies.session && session[cookies.session].expires > new Date()) {
        res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
        res.end(`${session[cookies.session].name}님 안녕하세요`);

    이 부분이 실행된다. 

     

    마지막에 session 에서 이름만 꺼내서 사용하는 것을 볼 수 있다. 

    즉, 브라우저는 서버로 세션 쿠키만 보내주고 서버쪽에서는 세션에 접근해서 이름을 꺼내와서 쓰는 것이다. 

    브라우저는 의미를 알 수 없는 키를 가지고 있는 것이고 그 키를 통해서 서버의 실제로 중요한 데이터에 접근을 하게 된다.

     

    *이해를 돕기 위해 세션을 직접 구현했지만 실 서버에서는 세션을 직접 구현하는건 지양하자.

    '노드' 카테고리의 다른 글

    노드 클러스터 cluster  (0) 2023.04.14
    노드 https, http2  (0) 2023.04.14
    노드 쿠키 이해하기  (1) 2023.04.13
    노드 POST, PUT, DELETE 요청 보내기  (0) 2023.04.13
    노드 REST API 서버 만들기  (1) 2023.04.13
Designed by Tistory.