사용자는 어떤 서비스를 이용하기 위해서는 자신이 누구인지 신뢰할 수 있는 지
에 대해서 인증을 거치고 권한을 얻을 수 있다.
인증을 거치는 절차에 있어서 Cookie, Session, Token, OAuth
가 대표적으로 사용되며 로그인(사용자를 인증하고 권한을 제어하는 행위) 할 때를 예시를 들 수가 있다.
🤔 쿠키는 어떻게 사용되며 왜 사용할까???
위에서도 언급했듯이 인증
을 하기 위해서 쿠키를 사용하며 쿠키를 통해 사용자를 인증할 수 있다. 이 때 쿠키는 데이터를 저장하는 조각
이라 생각할 수 있다.
한 마디로, 쿠키에 담긴 정보를 토대로 인증을 진행한다.
쿠키를 사용하는 또 다른 이유는 HTTP(Hyper Text Transfer Protocol)에 있다.
쿠키가 나온 이유를 설명하기 위해 http를 간략하게 소개하자면 http는 아래와 같이 크게 두 가지 특징 stateless, connectionless
의 특징을 가진다.
http는
웹에서 문서를 주고 받기 위해 지정된 통신규약
이다.http 특징
1. stateless(비상태성): 상태를 저장하지 않음
2. connectionless(비연결성): 클라이언트와 서버 사이의 연결을 유지하지 않음
웹 사이트에서 정보를 주고 받기 위해서 HTTP를 이용하지만 HTTP의 stateless(비상태성)
으로 인해 HTTP는 상태를 저장하지 않는다. 이 말은, 클라이언트와 서버가 통신 함에 있어서 정보를 저장할 수단이 없다는 것이다. 따라서, 정보를 저장하여 인증을 하기 위해 쿠키가 나온 이유 중에 하나다.
쿠키를 이용함으로써 장바구니에 저장된 아이템, 테마, 언어 등
다양한 정보를 이용하여 클라이언트에 따라 각기 다른 서비스를 제공할 수 있다. 또한 사용자의 행동을 분석
하여 tracking할 때도 쓰인다.
쿠키 확인해보기 👇
아래 이미지는 내가 네이버에 로그인을 했을 때 네이버에서 내 브라우저에 보내준 쿠키들이다.
이미지에서 빨간 박스는 쿠키를 어떻게 설정할지에 대한 option
이다.
쿠키는 서버가 클라이언트에게 설정을 하면 이후 클라이언트 → 서버, 서버 → 클라이언트 간의 소통에서 쿠키는 자동으로 http header
에 담겨서 전송된다.
위에서 대충 쿠키가 어떤 놈인지 알아봤으니 쿠키에 대해서 정리해보면 아래와 같다.
쿠키의 특징
- 쿠키는 정보를 저장할 수 있다.
- 쿠키는 클라이언트에 저장된다.
- 클라이언트에 최대 300개 쿠키를 저장 가능.
- 하나의 도메인 당 20개의 쿠키를 가질 수 있다.
- 하나의 쿠키는 4KB(=4096byte)까지 저장 가능하여 큰 데이터는 적합하지 않다.
쿠키 동작 순서
- 사용자가 웹사이트에 접근한다.
- 클라이언트가 서버로 페이지를 요청한다.
- 서버는 필요한 정보를 담아 쿠키를 생성하여 클라이언트에게 HTTP header에 담아 응답한다.
- 서버로부터 받은 쿠키는 클라이언트가 Storage에 저장한다.
- 이후 동일 사이트 재방문시 클라이언트의 PC에 해당 쿠키가 있는 경우, 요청 페이지와 함께 쿠키를 전송한다.
쿠키 옵션은 여러가지만 있지만 자주 쓰이는 것들인 Domain, Path, MaxAge, Expire, Secure, HttpOnly, SameSite
를 위주로 다룬다.
domain option은 쿠키의 도메인 옵션과 서버의 도메인이 같아야만 쿠키를 전송할 수 있다
.
도메인에 대해서 간략히 설명하자면, 브라우저에서 [http://www.localhost:4000/user/info](http://www.localhost:4000/user/info)
로 요청을 보낸다고 하면, 여기서 도메인은 localhost
가 된다. 다른 예를 들자면 [https://www.naver.com](https://www.naver.com)
이 있다면 도메인은 naver.com
이 된다.
즉, 쿠키 옵션에서 도메인에 대한 정보는 포트 및 서브 도메인 정보를 제외하고 딱 도메인 만을 의미한다.
이렇게 쿠키에서 domain option을 설정하게 되면 kakao로 보내야 할 쿠키를 naver로 잘못 보내는 일을 막을 수 있다.
path option은 서버에서 라우팅할 때 사용되는 경로에 쿠키를 보낼 수 있는지에 대한 여부
이다.
path는 [http://www.localhost:4000/user](http://www.localhost:4000/user/info)
와 같은 url에서 /user
가 path이다.
또한 path에 설정된 경로의 하위 경로에게도 쿠키를 보낼 수 있다.
예시를 들자면 요청하는 url이 [http://www.localhost:4000/user/info](http://www.localhost:4000/user/info)
이고 path=”/user”
라면 /user/info는 /user의 하위 경로이므로 쿠키를 보낼 수 있다는 것이다.
path의 default 값은 /
이다.
쿠키를 통해서 서버에게 인증을 한다고 했다. 하지만 만약에 쿠키가 탈취된다면??? 쿠키를 가지고 다른 사람이 인증하면 큰일날 것이다. 이러한 경우를 대비해 쿠키가 유효한 기간
을 정해 줄 수 있는데 이에 대한 옵션이 MaxAge이다.
MaxAge의 값으로는 ms단위가 아닌 초(s)단위를 가지며
정해 준 시간이 지나면 쿠키는 파괴된다.
Expires option은 MaxAge와 같은 옵션이지만 값에 날짜를 지정
해 준다. 즉, 만료날짜를 지정해준다.
여기서 MaxAge 또는 Expires를 지정하냐 지정하지 않냐에 따라서 Session Cookie(임시쿠키, 세션쿠키)와 Persistent cookie)
로 나뉜다.
브라우저가 실행 중일 때만 유효하고 브라우저를 끄면 사라지는 쿠키
이다.주어진 시간 동안만 살아있고 주어진 시간이 지나면 파기
된다.secure option은 http와 https에 따라 쿠키를 전송할 수 있는지에 대한 여부를 결정짓는 옵션이다.
하지만, localhost에서 개발을 많이 하므로 예외적으로 localhost에서는 Secure: true여도 http 요청을 할 수 있다.
스크립트(javascript)로 브라우저의 쿠키에 접근할 수 있는지에 대한 여부이다. javascript로 document.cookie
를 이용하여 쿠키를 얻을 수 있는데 이를 허용할지 말지인 것이다.
스크립트로 쿠키에 접근을 허용하지 않는다
.스크립트로 쿠키에 접근을 허용
한다.Cross-Origin 요청과 Same-Stie
인 경우에 대해서 쿠키를 전송할 수 있는지에 대한 여부이다.
Cross-Origin이 궁금하다면 CORS와 SOP
를 공부해보면 알 수 있다.
Cross-Origin요청일 시 GET메서드에 대해서만 쿠키 전송 가능
하다. same-site라면 메서드에 상관없이 쿠키 전송이 가능하다.same-site요청일 시에만 쿠키전송 가능.
Secure: true
옵션이 필요하다간단한 쿠키 생성
// server.js
const http = require("http");
const PORT = 4000;
const server = http
.createServer((req, res) => {
res.writeHead(200, {
"Set-Cookie": ["name=jjung", "address=seoul"],
});
res.end();
})
.listen(PORT, () => console.log(`server is listening at PORT: ${PORT}`));
express와 cookie option 지정
res.cookie
는 express에서 제공하는 메서드이다.
// server.js
const express = require("express");
const PORT = 4000;
// session cookie
const nameCookieOptions = {
domain: "localhost",
path: "/",
httpOnly: true, // script로 쿠키 접근 불가
secure: true, // sameSite가 none이므로 secure option은 필수적으로 설정 필요
sameSite: "none",
};
// persistent cookie
const addressCookieOptions = {
domain: "localhost",
path: "/",
httpOnly: true,
secure: true,
sameSite: "none",
expires: new Date(Date.now() + 1000 * 60 * 5),
};
const app = express();
app.get("/", (_, res) => {
res.cookie("name", "jjung", nameCookieOptions);
res.cookie("address", "seoul", addressCookieOptions);
res.status(200).send("<h1>I got cookies!!</h1>");
});
app.listen(PORT, () => console.log(`server is listening at PORT: ${PORT}`));
MaxAge 또는 Expires의 지정 여부에 따라 nameCookie는 session cookie
이며 addressCookie는 persistent cookie
가 됨을 알 수 있고 설정한 cookie option에 따라 잘 들어간 것을 확인할 수 있다.
쿠키를 이용하여 원하는 정보를 client에 담을 수 있음을 알았다. 하지만, 크롬 개발자 도구에서 cookie의 name과 value가 그냥 보인다…. 이는 보안의 취약점이 아닐 수가 없다… 만약에 비밀번호와 같은 것이 그대로 cookie에 담겨 외부인에게 노출된다면…. 흠… 비밀번호를 암호화하던 해야 할 것 같다. 아니면, server에서 비밀번호를 저장해 놓고 client에는 비밀번호를 제외한 쿠키를 놓든 하는 것도 방법일 듯 하다. 그리고 쿠키는 XXS, CSRF 공격에 취약하다는데 추가적으로 공부하면 좋을 듯 하다.
http reference
MaxAge VS Expires
CORS and CSRF
CORS and SOP
참고하면 좋은 사이트