Cookie & Session

Vorhandenheit ·2022년 1월 15일
0

JS/Node 

목록 보기
26/63

Cookie

쿠키는 클라이언트 측에서 웹브라우저에 저장되는 데이터 입니다.
왜 클라이언트 측에 데이터를 저장하냐면 HTTP의 특징 중에 Connectionless와 Stateless 때문입니다. 매번 연결할때마다 다시 접속해서 인증을 받는 것은 비효율적입니다. State를 유지해주기 위해서 cookie를 사용합니다.

Connectionless
HTTP는 클라이언트가 요청(request)를 서버에 보내고, 서버는 클라이언트에게 응답(response)를 주고 연결을 끊습니다.

Stateless
connection을 끊는 순간 클라이언트와 서버의 통신이 끝나며 상태정보는 유지하지않는 특성입니다.

1. 특징

  • 이름, 값, 만료일(저장기간), 경로 정보로 구성되어 있습니다.
  • 클라이언트에 총 300개의 쿠키를 저장 할 수 있습니다.
  • 하나의 도메인 당 20개의 쿠키를 가질 수 있습니다.
  • 하나의 쿠키는 4kb까지 저장 가능합니다.

2. 목적

  1. 세션 관리 : 로그인, 사용자 닉네임, ㅈㅂ속 시간, 장바구니 등의 서버가 알아야할 정보들을 저장
  2. 개인화 : 사용자마다 다르게 그 사람에게 적절한 페이지를 보여줄 수 있습니다.
  3. 트래킹 : 사용자의 행동과 패턴을 분석하고 기록합니다.

3. 동작 순서

  • 클라이언트가 페이지를 요청합니다.
  • 웹서버는 쿠키를 생성합니다.
  • 생성한 쿠키의 정보를 담아서 HTTP 화면에 돌려줄 때, 같이 클라이언트에게 돌려줍니다
  • 넘겨받은 쿠키는 클라이언트가 가지고 있다가 다시 서버에 요청할 때 요청과 함께 쿠키를 전송합니다.
  • 동일 사이트 재방문 시 클라이언트의 PC에 해당 쿠키가 있는 경우, 요청 페이지와 함께 쿠키를 전송합니다.

4. 쿠키 옵션

(1) Domain

  • domain=site.com
    쿠키에 접근 가능한 domain을 지정합니다. domain 옵션에 아무값도 넣지않으면, 쿠키를 설정한 도메인에서만 쿠키에 접근할 수 있습니다.

(2) Path

  • path=/example
    해당 디렉토리와 하위 디렉토리에서만 경로가 활성화되고, 웹 브라우저는 해당하는 쿠키만 웹 서버에 전송합니다. 절대경로여야하고, (미 지정시) 기본값은 현재 경로입니다.

(3) MaxAge or Expires

  • expires= Tue, 19 Jan 2022 03:14:07 GMT
  • max-age=3600
    쿠키가 유효한 기간을 정하는 옵션입니다.
    MaxAge는 앞으로 몇초 동안 쿠키가 유효한지 설정하는 옵션입니다.
    Expires는 언제까지 유효한지 Date를 지정합니다

(4) Secure

(5) HttpOnly

자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정합니다. 명시되지않은 경우 false로 지정되어있습니다.

(6) SameSite

Cross-origin 요청을 받은 경우 요청에서 사용한 메소드와 해당 옵션의 조합으로 서버의 쿠키 전송 여부를 결정하게 됩니다.
samesite는 XSRF를 막기 위해 만들어진 옵션입니다.

XSRF (cross-site request forgery)
현재 bank.com에 로그인되어있다고 가정할 때, 해당 사이트에서 사용되는 인증 쿠키가 브라우저에 저장되고, 브라우저는 bank.com에 요청을 보낼때마다 인증 쿠키를 함께 전송할 것입니다.
서버는 전송받은 쿠키를 이용해 사용자를 식별하고, 보안이 필요한 재정 거래를 처리합니다.
로그아웃하지않고 다른 창을 띄워서 웹 서핑을 하던 도중에 뜨하지않게 evil.com에 접속했을 때, 이 사이트의 해커에게 송금을 요청하는 폼이 있고, 이 폼이 자동으로 제출되도록 설정되어있을 때, 폼이 evil.com에서 은행사이트로 바로 전송될 때 인증 쿠키도 함께 전송이됩니다. bank.com에 요청을 보낼땜다 bank.com에서 설정한 쿠키가 전송되기 때문입니다.

  • samesite=lax : Cross-origin 요청이면 'GET' 메소드에 대해서만 쿠키를 전송할 수 있습니다.
  • samesite=strict : Cross-origin이 아닌 same-site인 경우에만 쿠키를 전송할 수 있습니다.
  • None : 항상 쿠키를 보내줄 수 있습니다. 다만 쿠키 옵션 중 Secure옵션이 필요합니다.

5. 쿠키 사용

익스프레스에서 cookie-parser 모듈을 이용해 쿠키를 설정하거나 사용할 수 있습니다.

  • 설치
npm install cookie-parser
  • 사용
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser()); // cookieParser(secretKey, optionObj)

암호화된 쿠키를 사용하기 위해서는 cookieParser() 메소드의 인자로 임의의 문자열을 전달하면 됩니다.

  • 쿠키 생성
res.cookie('쿠키이름', '쿠키 값', '옵션');
  • 예시
app.use(cookieParser('password'));

const cookieConfig = {
	httpOnly: true,
  maxAge: 100000,
  signed: true
};

app.get('/set', (req, res) => {
	res.cookie('key', 'value', cookieConfig);
  	res.send('set cookie');
});

app.get('/get', (req, res) => {
	res.send(req.cookie);
})

Session


세션은 쿠키를 기반으로 하고있지만, 사용자 정보 파일을 브라우저에 저장하지않고 세션은 서버 측에서 관리합니다.

1. 특징

  • 웹 서버에 웹 컨테이너의 상태를 유지하기 위한 정보를 저장합니다.
  • 웹 서버의 저장되는 쿠키(=세션 쿠키)
  • 브라우저를 닫거나, 서버에 세션을 삭제했을때만 삭제가 되므로, 쿠키보다 비교적 보안이 좋습니다.
  • 각 클라이언트 고유 Session ID를 부여합니다.

2. 동작 순서

    1. 클라이언트가 페이지를 요첩합니다
    1. 서버는 접근한 클라이언트의 Request-Header 필드인 Cookie를 확인하여, 클라이언트가 해당 session-id를 보냈는지 확인합니다.
    1. session-id가 존재하지않는다면, 서버는 session-id를 생성해 클라이언트에게 돌려줍니다.
    1. 서버에서 클라이언트로 돌려준 session-id를 쿠키를 사용해 서버에 저장합니다.
    1. 클라이언트 재접속 시, 이 쿠키를 이용하여 session-id값을 서버에 전달합니다.

3. session 메소드

  • save(callback)
    세션을 store에 명시적으로 저장하는 메소드입니다.
req.session.save(function(err) {
})
  • destroy(callback)
    세션을 명시적으로 삭제하는 메소드입니다.
req.session.destroy(function(err) {
})
  • reload(callback)
    store에 저장된 session date를 다시 불러오는 메소드입니다
req.session.reload(function(err) {
})
  • regenerate(callback)
    세션을 재생성하는 메소드로, SID가 새로 부과됩니다. callback 재생성후 수행할 함수를 전달해주면 됩니다.
req.session.regenerate(function(err) {
})
  • touch()
    명시적으로 maxAge를 갱신합니다.
req.session.touch()

4. session 옵션

  • cookie
    SID 쿠키에 대한 설정입니다. cookie옵션을 객체 형식으로 줄 수 있고
    default는 {path: '/', httpOnly: true, secure: false, maxAge: null} 입니다.

  • genid
    SID로 사용할 로직을 정의하는 옵션입니다. genid: function(req) {} 형식으로 사용하면 되고, SID로 사용할 String을 return 하면 됩니다. default로 uid-safe라이브러리를 통한 SID 생성 함수를 사용합니다.

  • name
    SID 쿠키의 이름을 설정합니다. default는 connect.sid입니다.

  • proxy
    리버스 프록시를 사용하는 경우 설정하는 옵션입니다. true로 설정하면 X-Forwarded-Proto헤더가 사용됩니다. default는 undefined로, express에 trust proxy로 등록된 주소에 대해서만 세션이 동작합니다.

  • resave
    express-session은 기본적으로 세션에 변경이 있을 때만 세션을 저장합니다. resave:true로 설정한다면 변경사항이 없어도 session을 다시 저장합니다. default는 true입니다. false로 설정하면 불필요한 session 저장을 막아주기 때문에 보통 false로 설정합니다.

  • saveUninitialized
    세션이 생성되었지만 어떠한 데이터도 추가되거나 변경되지 않은 상태를 uninitialized라고 합니다.
    saveUninitialized: ture로 설정한다면 uninitiazlied session도 저장합니다.
    false로 설정하면 uninitiazlied session은 저장하지 않으므로 리소스 활용측면에서 조금 더 유리합니다.

  • rolling
    세션이 만료되기 전, 새로고침 또는 페이지 이동이 일어나면 세션 만료를 갱신하느느 옵션입니다.
    default는 rolling:false입니다.

saveUninitiazlied 옵션이 false인 경우 uninintialized 세션에 대해서는 rolling이 작동하지않습니다. 따라서 단순히 로그인 여부 확인을 위해 session을 사용한다면 saveUninitialized 옵션을 true로 설정해줘야합니다.

  • secret
    필수적으로 설정해줘야하는 옵션입니다. SID를 생성할 때 사용되는 비밀키로 String 또는 Array를 사용할 수 있습니다. Array를 사용하는 경우, 첫 번쨰 요소를 비밀키로 사용합니다.

  • store
    세션을 어디에 저장할지 결정하는 옵션입니다. default는 MemoryStore로 메모리에 저장됩니다. 따라서 프로세스가 종료되면 세션이 없어집니다.

  • unset
    삭제된 session을 어떻게 관리할지 결정하는 옵션입니다. destroykeep을 사용할 수 있는데, destroy는 response가 끝날 때 store에서 삭제하는 옵션, keep은 store에서 삭제하지는 않지만 더 이상 변경할 수 없게 하는 옵션입니다. default는 keep입니다.

5. session 사용

익스프레스에서 express-session 모듈로 세션을 지원합니다.

  • 설치
npm install express-session
  • 사용
const express = require('express');
const session = require('express-session');
const app = express();

app.use(session({
	secret: 'password',
  	resave: false,
  	saveUninitialized: true
}));
  • secret : 보안을 위한 임의의 문자열(secret key)

  • resave : 세션 데이터가 바뀌기 전까지 세션 저장소의 값을 저장할지 여부(default: false)

  • saveUninitialized : 세션이 필요하기 전에 세션을 구동할지 여부(default: true)

  • store : 세션 저장소를 지정

  • 예시

const express = require('express');
const session = require('express-session'); //express-session 모듈을 로드합니다.
const FileStore = require('session-file-store')(session); // 데이터베이스에 접속하는 것으로 정보를 객체로 저장해둡니다.
const app = express();

app.use(session({ // 사용자의 요청이 있을 때마다 해당 코드가 실행이 됩니다.
	secret: 'password', 
  	resave: false,
  	saveUninitialized: true,
  	store: new FileStore()
}));

app.get('/', function (req, res, next) {
	if (req.session.num === undefined) {
    	req.session.num = 1;
    }
  	else {
    	req.session.num = req.session.num+1;
    }
  res.send(`views: ${req.session.num}`)
})

session middleware
HTTP 통신을 할 때, 서버가 쿠키를 발행하고 클라이언트가 쿠키를 저장합니다. 그리고 나중에 재접속 할 때 서버는 클라이언트의 쿠키의 값을 확인합니다.
세션을 이용한다면 쿠키에 세션의 sid값을 저장해둡니다. 따라서 서버에는 sid 값을 가지고 서버내부에 저장되어있는 데이터베이스 혹은 파일과 비교하여 내용을 확인합니다.

  • const FileStore = require('session-file-store')(session);
    위 소스를 실행하면 req.session 내용이 파일로 생성되어 저장되고, 생성된 파일을 보면 요청할 때마다 num값이 바뀌는 걸 볼 수 있습니다.

express-session을 사용하면 request.session이라는 객체가 생성됩니다. 해당하는 객체에 property를 할당함으로 세션에 값을 줍니다.


쿠키와 세션의 차이

(1) 저장위치

쿠키는 클라이언트에 메모리 또는 파일에 저장하고, 세션은 서버 메모리에 저장됩니다.

(2) 보안

쿠키는 클라이언트에 로컬에 저장되기도하고 특히 파일로 저장하는 경우 탈취, 변조될 위험이 있고, Request/Response에서 스나이핑 당할 위험이 있어 보안이 비교적 취약합니다. 반대로 session은 클라이언트 정보 자체는 서버에 저장되어 있으므로 비교적 안전합니다.

(3) 라이프 사이클

쿠키는 앞서 설명한 지속 쿠키의 경우에 브라우저를 종료하더라도 저장되어 있을 수 있는 반면에 세션은 서버에서 만료시간/날짜를 정해서 지워버릴 수 있기도 하고 세션 쿠키에 세션 아이디를 정한 경우, 브라우저 종료시 세션 아이디가 날아갈 수 있습니다.

(4) 속도

세션을 주로 사용하면 되는데 왜 굳이 쿠키를 사용할까?
세션은 서버에 데이터를 저장 즉, 서버의 자원을 사용하기 때문에 서버 자원에 한계가 있고 메모리를 사용하다보면 속도 저하가 올 수 있기 때문입니다.

출처

https://nesoy.github.io/articles/2017-03/Session-Cookie
https://interconnection.tistory.com/74
https://devuna.tistory.com/23
https://cotak.tistory.com/87
https://ko.javascript.info/cookie
https://lhwn.tistory.com/entry/1-Nodejs-express-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%9D%98-session

profile
읽고 기록하고 고민하고 사용하고 개발하자!

0개의 댓글