노드 세션 사용하기
쿠키의 정보는 노출되고 수정되는 위험이 있다. 해결방법은 다음과 같다
- 중요한 정보는 서버에서 관리하고 클라이언트에는 세션 키만 제공
- 서버에 세션 객체(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 에서 이름만 꺼내서 사용하는 것을 볼 수 있다.
즉, 브라우저는 서버로 세션 쿠키만 보내주고 서버쪽에서는 세션에 접근해서 이름을 꺼내와서 쓰는 것이다.
브라우저는 의미를 알 수 없는 키를 가지고 있는 것이고 그 키를 통해서 서버의 실제로 중요한 데이터에 접근을 하게 된다.
*이해를 돕기 위해 세션을 직접 구현했지만 실 서버에서는 세션을 직접 구현하는건 지양하자.