쿠키는 서버에서 클라이언트에 영속성있는 데이터를 저장하는 방법이다.
어떤 웹사이트에 들어갔을 때, 서버가 일방적으로 클라이언트에 전달하는 작은 데이터라고 할 수 있다
서버는 클라이언트의 쿠키를 이용하여 데이터를 가져올 수 있다.
서버에서 클라이언트에 쿠키를 전송하는 것과 클라이언트에서 서버로 쿠키를 다시 전송하는 것도 포함된다. 서버가 클라이언트에 특정한 데이터를 저장할 수 있으며 특정 조건들이 만족되어야 다시 가져올 수 있다. 쿠키는 http의 stateless한 것을 보완해주는 도구이며 서버에 부담을 덜어주지만 쿠기 그 자체가 인증은 아니다
'Set-Cookie':[
'cookie=cookie',
'Secure=Secure; Secure',
'HttpOnly=HttpOnly; HttpOnly',
'Path=Path; Path=/cookie',
'Domain=Domain; Domain=cookie.com'
]
Domain: 서버와 요청의 도메인이 일치하는 경우 쿠키 전송
도메인은 www.google.com과 같은 서버에 접속할 수 있는 이름이다
쿠키 옵션에서 도메인은 포트 및 서브 도메인 정보, 세부 경로를 포함하지 않으므로 google.com이 도메인이 된다. (서브 도메인 - www 같은 도메인 앞에 추가로 작성되는 부분)
쿠키 옵션에서 도메인 정보가 존재할 경우 클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송할 수 있다.
Path: 서버의 요청의 세부 경로가 일치하는 경우 쿠키 전송
Path는 세부 경로로써 서버가 라우팅할 때 사용하는 경로를 의미한다.
요청해야 하는 URL이 http://www.localhost.com:3000/users/login인 경우에는 Path는 /users/login이 된다. 이를 명시하지 않으면 기본적으로 /으로 설정되어 있다
Path 옵션은 /users/mypage처럼 설정된 경로를 포함하는 하위 경로로 요청을 하더라도 쿠키를 서버로 전송할 수 있다. /posts/mypage로 전송되는 요청은 Path 옵션을 만족하지 못하므로 서버로 쿠키를 전송할 수 없다
MaxAge / Expires: 쿠키의 유효기간 설정
쿠키가 유효한 기간을 정하는 옵션이며 쿠키가 영원히 남아있다면 탈취될 수 있으므로 유효기간을 설정하는 것은 보안 측면에서 중요한 부분이다.
MaxAge : 쿠키가 유요한 시간을 초 단위로 설정하는 옵션이다
Expires : 언제까지 쿠키가 유효한지 정할 수 있으며 옵션의 값은 클라이언트 시간을 기준으로 한다
쿠키의 위 옵션의 여부에 따라 세션 쿠키와 영속성 쿠키로 나눠진다
세션쿠키 : MaxAge 또는 Expires 옵션이 없는 쿠키이며 브라우저가 실행 중일 때 사용할 수 있는 임시 쿠키이다. 브라우저가 종료하면 해당 쿠키는 삭제된다.
영속성 쿠키 : 브라우저의 종료 여부와 상관없이 MaxAge 또는 Expires에 지정된 유효시간만큼 사용가능한 쿠키이다
Secure : HTTPS에서만 쿠키 전송 여부 결정
사용하는 프로토콜에 따른 쿠키의 전송 여부를 결정하는 옵션이다.
Secure 옵션이 true로 설정된 경우 ➡ HTTPS를 이용하는 경우에만 쿠키를 전송한다.
Secure 옵션이 없는 경우 ➡ 프로토콜에 상관없이 모두 쿠키를 전송한다.
도메인이 localhost인 경우 ➡ 개발 단계에서 사용하는 경우가 많아 HTTPS가 아니여도 쿠키 전송이 가능하다.
HttpOnly : DOM을 이용해 쿠키에 접근하는 것을 막아주는 옵션
자바스크립트로 브라우저의 쿠키에 접근이 가능한지 여부를 경정한다.
옵션이 true로 설정된 경우 ➡ 자바스크립트로 쿠키에 접근이 불가
옵션이 명시되지 않는 경우는 기본적으로 false로 지정 ➡ document.cookie를 이용해 자바스크립트로 접근이 가능하다. (쿠키에 접근할 수 있어서 쿠키가 탈취될 위험이 있다)
SameSite : CORS 요청에 대한 쿠키 전송 여부 결정
Cross-Origin 요청을 받은 경우에 요청에서 사용한 메소드(GET, POST, PUT, PATCH 등)와 해당 옵션의 조합을 기준으로 서버의 쿠키 전송 여부를 경정한다
Lax : Cross-Origin 요청이라면 GET 메소드에 대해서만 쿠키를 전송
Strict : 단어 그대로 가장 엄격한 옵션, Cross-Origin이 아닌 same-site인 경우에만 쿠키를 전송
None : 사이트가 달라도 모든(GET, POST, PUT 등) 요청에 쿠키를 보낼 수 있음, 쿠키 옵션 중 Secure 옵션이 필요
➡ same-site는 요청을 보낸 Origin과 서버의 도메인, 프로토콜, 포트가 같은 경우를 말하며 하나라도 다를 경우에는 Cross-Origin으로 구분된다
쿠키의 특성을 이용하여 Stateless한 인터넷 연결을 Stateful하게 유지할 수 있다
하지만 쿠키는 오랜 시간 동안 유지될 수 있으며 HttpOnly 옵션을 사용하지 않을 경우에는 자바스크립트로 쿠키에 접근할 수 있으므로 개인정보와 같은 민감한 정보를 담는 것은 위험하며 2차 피해가 발생될 수 있다
서버가 Client에 유일하고 암호화된 ID를 부여하며 중요한 데이터는 서버에서 관리한다.
접속 상태를 서버가 가지며 접속 상태와 권한 부여를 위해 세션아이디를 쿠키로 전송한다. 신뢰할 수 있는 유저인지 서버에서 추가로 확인 가능하다. 하나의 서버에서만 접속 상태를 가지므로 분산에 불리하다는 단점이 있다.
로그인
사용자가 정확한 아이디와 비밀번호를 입력했다면 서버는 인증에 성공했다고 판단한다
그 다음에 인증을 필요로 하는 작업을 추가로 요청할 경우에는 서버가 인증에 성공했다고 알고 있으므로 유저가 매번 로그인을 하지 않아도 된다 ➡ 인증에 따라 리소스의 접근 권한(Authorization)이 달라진다
서버 : 사용자가 인증에 성공했음을 알고 있어야 한다
클라이언트 : 인증 성공을 증명할 수단을 갖고 있어야 한다
➡ 사용자가 인증에 성공한 상태는 세션이며 서버는 일종의 저장소(in-memory, 세션 스토어)에 세션을 저장
➡ 세션이 만들어진 후에 각 세션을 구분할 수 있는 세션 아이디가 만들어지며 클라이언트에 세션 성공을 증명할 수단
➡ 웹사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용, 쿠키에는 서버에서 발급한 세션 아이디를 저장
➡ 쿠키를 통해 유효한 세션 아이디가 서버에 전달, 세션 스토어에 해당 세션이 존재할 경우에는 서버는 접근 가능하다고 판단하며 쿠키에 세션 아이디가 없을 경우에는 서버는 해당 요청이 인증되지 않았다고 알려줌
로그아웃
세션 아이디가 담긴 쿠키는 클라이언트에 저장되어 있으며 서버는 세션을 저장하고 있으며 서버는 세션 아이디로만 인증 여부를 판단한다. 로그아웃은 서버에서 세션 정보를 삭제하거나 클라이언트에서 res.cookie로 쿠키를 갱신 또는 res.clearCookie로 쿠키를 삭제해야 한다.
express-session
Node.js에서 세션을 대신 관리해주는 모듈이다express-session은 세션을 위한 미들웨어이며 express 서버에서 쉽게 세션을 위한 공간을 다룰 수 있다. 세션의 경우 secret 옵션의 비밀키를 이용하여 암호화를 한 세션 id를 생성하며 클라이언트에게 쿠키로 전송한다. 쿠키로 전송된 세션 id는 고유한 세션 객체를 가지며 서버에 저장된다. 클라이언트에 유저의 개인정보를 담지 않고도 서버가 클라이언트의 세션 id를 이용하여 유저의 인증여부를 판단할 수 있다. 세션 객체는 req.session으로 접근할 수 있으며 세션의 임의의 데이터를 저장하거나 불러올 수 있다.
const express = require('express');
const session = require('express-session');
const app = express();
app.use(
session({
secret: '@jungmin',
resave: false,
saveUninitialized: true,
cookie: {
domain: 'localhost',
path: '/',
maxAge: 24 * 6 * 60 * 10000,
sameSite: 'none',
httpOnly: false,
secure: true,
},
})
);