웹 쿠키과 스토리지
이전 게시글에서 쿠키, 세션, 토큰 서버가 클라이언트 인증을 확인하는 방식에는 3가지(쿠키, 세션, 토큰)가 있다고 설명하였다.
서버는 사용자 자체를 인식하는 것이 아니라 사용자가 가진 인식표를 인식하는 것이고, 이 인식표는 언제든지 탈취될 가능성이 있기 때문에 아주 세심하게 관리해야 한다.
이 인식표를 어떻게 관리해야 하는지 알아보기 위해 브라우저 저장소들이 정확히 어떤 목적을 위해 어떤 방식으로 사용되고 주의점은 어떤 것들이 있는지 알아보고자 한다.
브라우저는 개발자를 위해 스토리지, 쿠키 이렇게 두 가지 종류의 저장소를 제공한다.
스토리지
1. 세션 스토리지
세션 스토리지는 말 그대로 세션을 위한 저장 공간이며 세션이 종료되면 모두 삭제된다.
만약 여러 개의 탭을 사용하면 탭 별로 세션 스토리지를 사용한다. 상당히 큰 저장 공간(5~10MB)을 가진다.
2. 로컬 스토리지
로컬 스토리지의 데이터는 반 영구적으로 저장가능하다.
새로고침을 하거나 브라우저를 껐다 켜도 유지되야하는 정보는 반드시 로컬 스토리지에 저장해야 한다. 상당히 큰 저장 공간(5~10MB)을 가진다.
ex) 장바구니나 사용자가 작성 중이던 글 등 여러 정보를 저장
스토리지 단점: XSS 공격
1
2
3
4
5
6
7
8
9
// 로컬 스토리지에서 token1 아이템을 문자열로 가져오기
const token1 = localStorage.getItem("token1");
// 세션 스토리지에서 token2 아이템을 문자열로 가져오기
const token2 = sessionStorage.getItem("token2");
// 로컬 스토리지에 token1 아이템을 Hi 라는 문자열로 설정하기
localStorage.setItem("token1", "Hi");
// 세션 스토리지에 token2 아이템을 Hello 라는 문자열로 설정하기
sessionStorage.setItem("token2", "Hello");
로컬 스토리지와 세션 스토리지는 위 예시와 같이 간단한 js 코드로 사용할 수 있다.
이 스토리지들은 클라이언트에서 실행 되는 어떤 js 코드에서든 간단히 접근 가능하다. 그래서 XSS(Cross Site Scripting)에 굉장히 취약하다.
다만 좋은 소식은 최신 프론트엔드 프레임워크 대부분은 어느정도 XSS를 차단해준다는 점 이다.
⚠️ 브라우저 스토리지는 XSS 공격에 매우 취약하다.
쿠키
쿠키는 HTTP 통신의 무상태성을 보완해주기 위해 나온 것으로 서버가 클라이언트에 값을 저장하고, 읽을 수 있도록 해준다.
1
Set-Cookie: my_name=Lifthus; Expires=Sun, 07 Apr 2023 00:00:00 GMT; Domain=.example.com; Path=/; HttpOnly; Secure; SameSite=Lax
쿠키는 서버의 응답 헤더에 위와 같은 형태로 작성된다. 왜 그냥 쿠키가 아니라 Set-Cookie 일까?
Set-Cookie 헤더는 그 자체로 저장소가 아니라 말 그대로 서버가 브라우저에게 이 쿠키들을 Set 하라는 명령이라 생각하면 된다.
브라우저가 해당 헤더를 받으면 서버의 명령대로 내부적으로 쿠키 값을 저장하고, 이후 요청들의 Cookie 헤더에 포함해 다시 서버로 보낸다.
매우 작은 저장 공간(4KB)을 가지며 쿠키는 모두 일정 기간이 지나면 삭제된다.
만료 시점에 따라
- session cookies: 브라우저가 종료되면 삭제
- persistent cookies: 지정된 만료일에 삭제
쿠키 특성
쿠키의 가장 중요한 특성은 서버에서 접근할 수 있으며, 자동으로 요청에 포함된다는 점이다.
다음은 네이버에 들어갔을 때 Response Header이며 set-cookie를 통해 클라이언트에 쿠키를 설정하는 것을 볼 수 있습니다. 이들은 따로 설정하지 않아도 자동으로 다음 요청에 같이 포함된다.
쿠키 속성
쿠키에는 key, value 값 외에 추가로 몇 가지 속성들을 가지고 있는데, 각 속성들에 대해 알아보자.
Expires: 쿠키의 만료 시간
Domain: 브라우저는 해당 도메인에대한 요청에서만 해당 쿠키를 포함(쿠키의 노출 범위 줄여줌)
Path: 해당 Path에서만 해당 쿠키가 사용(쿠키의 노출 범위 줄여줌)
HttpOnly: 브라우저에게 쿠키를 클라이언트 코드에서 접근할 수 없게 하라는 명령(XSS에 대해 안전을 확보)
어디에 무엇을 저장?
보안이 크게 중요하지 않다면 로컬 스토리지는 나쁘지 않은 선택이 될 수 있다. 쿠키와 다르게 반 영구적으로 많은 저장 공간을 사용할 수 있기 때문에 처음에 한 번 인증만으로 다시는 인증을 하지 않아도 되도록 편하게 구현할 수 있다.
하지만 보안의 측면에서 웹 스토리지(로컬 스토리지 + 세션 스토리지)는 좋지 못하다고 할 수 있다.
웹 스토리지에 저장된 값은 javascript 코드를 통해 언제든지 접근할 수 있는데, 이는 웹 사이트에 악의적인 스크립트를 넣어 의도하지 않은 동작을 발생시키는** XSS(cross-site scripting)공격에 취약**하다.
반면 쿠키에 저장한 값은 HttpOnly 속성을 통해 javascript를 통한 접근을 막을 수 있다. 때문에 보안적인 측면을 생각한다면 웹 스토리지보다는 쿠키에 저장하는 것이 좋다고 할 수 있다.
로그인한 토큰을 저장한다고 생각했을 때, 로그인은 보안이 중요하고 로그인 확인을 위해 토큰을 서버에 요청 시 매번 전달해야한다.
이에 적합한 브라우저 저장소는 XXS 공격을 막을 수 있고 토큰 값이 서버의 요청에 자동으로 포함되는 쿠키라고 할 수 있다.
(쿠키는 서버의 요청에 자동으로 포함되는 반면 스토리지는 쿠키와 다르게 서버에서 접근할 수 없기 때문에, 클라이언트에서 스토리지의 값을 꺼내서 서버에 전달해주어야 한다.)
📑 참고 자료