Node.js_쿠키와 세션

Node.js 2021. 7. 2. 12:53

(본 포스팅은 길벗의 'Node.js 교과서' 책을 공부하면서 작성되었습니다_내돈내산) 

 

  • 로그인 로그아웃 동작을 위해 필수적으로 알아두어야 할 개념

1. 쿠키 (Cookie)
- 키=값의 쌍(name=ggaebong)
- 매 요청마다 서버에서 동봉해서 보냄
- 서버는 쿠키를 읽어 누구인지 파악하게 됨.
- 처음에 서버에서 쿠키를 보내주면 다음부터에서는 브라우저에서 쿠키값을 넣어서 요청하게 된다.
- 브라우저를 끄면 쿠키가 사라지게 된다.(만료기간을 별도로 지정하지 않을경우)

// 쿠키삽입 기본 예제
const http = require('http');

http.createServer((req,res)=>{
  console.log(req.url, req.headers.cookie);
  // 요청헤더에 입력하는 메서드
  // Set-Cookie: 브라우저에게 쿠키를 설정하라고 명령
  res.writeHead(200, { 'Set-Cookie' : 'mycookie = test' }); 
  res.end('Hello Cookie');
})
  .listen(8083, () => {
    consol.log('8083포트에서 서버 대기 중입니다.')
  })
// 쿠키 예제 2
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;
    }, {});

http.createServer(async (req, res) => {
  const cookies = parseCookies(req.headers.cookie); // { mycookie: 'test' }
  // 주소가 /login으로 시작하는 경우
  if (req.url.startsWith('/login')) {
    const { query } = url.parse(req.url);
    const { name } = qs.parse(query);
    const expires = new Date();
    // 쿠키 유효 시간을 현재시간 + 5분으로 설정
    expires.setMinutes(expires.getMinutes() + 5);
    // 302 status code는 redirect 시키겠다는 뜻
    res.writeHead(302, {
    // name에는 문자를 사용할수 없기에 encodeURIcomponent를 사용해 브라우저에서 사용가능하도록 인코딩해주어야함.
    // Expires로 만료기간을 설정하면 만료 후에는 브라우저가 요청과함께 쿠키를 보내지 않음
    // HttpOnly의 경우 자바스크립트로 쿠키에 접근할수 없게해 보안성을 높임
    // path옵션: 제시된 경로 이하에서는 모두 쿠키가 유효하다는것
      Location: '/',
      'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`,
    });
    res.end();
  // name이라는 쿠키가 있는 경우
  // 이미 쿠키를 한번 담아서 브라우저에 응답을 보냈을 경우 브라우저는 이미 쿠키를 가지고 있음.
  } else if (cookies.name) {
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(`${cookies.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(8084, () => {
    console.log('8084번 포트에서 서버 대기 중입니다!');
  });

 

2. 세션 (Session)

- 직접적인 정보들은 쿠키에 넣어놓으면 보안적으로 좋지 않기 때문에 값은 서버단에서 가지고 있고, 접근가능한 key만 브라우저로 보내주는 방법인 세션이 있다.

- 서버에 세션(session) 객체 생성 후, uniqueInt(키)를 만들어 속성명으로 사용
- 속성값에 정보를 저장하고 uniqueInt를 클라이언트쪽으로 보내준다.

- 실무에서는 express-session을 이용해서 사용하도록 한다. 보안적으로 매우 좋지 않게 된다

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, {
    // 고유값을 가지고 서버에서 session에 있는 값을 조회할 수 있도록 함.
      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번 포트에서 서버 대기 중입니다!');
  });

'Node.js' 카테고리의 다른 글

Node.js_패키지 매니저(npm)  (0) 2021.07.02
Node.js_클러스터(Cluster)  (0) 2021.07.02
Node.js_HTTP 모듈로 서버 만들기  (0) 2021.07.01
Node.js_버퍼(buffer)와 스트림(stream)  (0) 2021.07.01
Node.js_파일 시스템(fs)  (0) 2021.07.01
admin