쿠키와 세션 그리고 JWT

hyelim·2023년 5월 5일
1
post-thumbnail

기존 http의 경우엔 보안을 위해서 stateless 한 방식을 사용한다.
이는 통신이 끊기면 계속해서 추가로 입력했던 정보를 다시 요구하기 때문에 매우 불편하다

이것의 단적인 예로 로그인을 했다가 서버를 끄고 켰을 때 다시 로그인 작업을 해야하는 등의 불편함이 이에 해당한다.

이를 해결하기 위해서 http에서 조금 더 안전하게 stateful한 상태를 유지하고자 고민을 하던 도중 session, cookie, jwt 라는 방식을 알게 되었고 조금 더 안전한 페이지를 만들고자 jwt를 도입하게 됐다.

이제 쿠키, 세션, JWT 에 대해 하나씩 알아보자

먼저 쿠키와 세션에 대해 알아보자

앞서 말했듯이 쿠키와 세션은 HTTP 프로토콜의 한계(Connectionless, Stateless)를 극복하기 위해 생긴 상태를 저장하기 위해 생긴 기술이다

쿠키

쿠키는 인터넷을 사용하는 유저가 어떤 웹사이트를 방문했을 때 그 사이트가 사용하는 서버를 통해 로컬에 저장되는 작은 데이터

key, value로 이루어져있음

쿠키는 브라우저에 저장되는 작은 크기의 문자열로, HTTP 프로토콜의 일부

쿠키는 주로 웹 서버에 의해 만들어지고, 서버가 HTTP 응답 헤더의 Set-Cookie 에 내용을 넣어 전달하면, 브라우저는 이 내용을 로컬에 저장한다. 브라우저는 사용자가 쿠키를 생성하도록 한 사이트에 접속할 때마다 쿠키의 내용을 요청 헤더에 넣어서 함께 전달한다

여기서의 핵심은 로컬에 저장한다는 것이다

쿠키 특징

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

쿠키 생성과정

  1. 클라이언트가 페이지를 요청한다. (사용자가 웹사이트에 접근)
  2. 웹 서버는 쿠키를 생성한다.
  3. 생성한 쿠키에 정보를 담아 HTTP 화면을 돌려줄 때, 같이 클라이언트에게 돌려준다.
  4. 넘겨받은 쿠키는 클라이언트가 가지고 있다가(로컬 PC에 저장) 다시 서버에 요청할 때 요청과 함께 쿠키를 전송한다.
  5. 동일 사이트 재방문 시 클라이언트의 PC에 해당 쿠키가 있는 경우, 요청 페이지와 함께 쿠키를 전송한다.

여기서 쿠키는 브라우저에 저장되기 때문에 사용자가 다른 브라우저를 사용하거나 쿠키를 삭제하면 데이터가 손실될 수 있다

쿠키 전달과정

쿠키 장단점

장점

사용자의 정보를 방문 시에 저장하고 있기 때문에 방문 시마다 확인해야할 번거로운 작업을 편리하게 처리 가능

웹사이트를 운영하는 입장에선 사용자가 저장한 쿠키 정보를 이용해 사용자의 행동과 패턴을 분석하고 트래킹 가능

단점

  • 데이터 노출 위험: 쿠키는 클라이언트(브라우저)에 저장되는 정보이므로, 누군가가 해당 사용자의 컴퓨터에 접근하면 쿠키 내용을 확인할 수 있다. 따라서 중요한 개인 정보나 인증 데이터를 쿠키에 저장하면 해당 정보가 유출될 수 있는 위험이 있다.

  • 쿠키 변조: 쿠키는 클라이언트가 서버로 전송하는 요청에 첨부되어 보내지므로, 해커는 이를 이용하여 쿠키 값을 변조할 수 있다. 이를 통해 다른 사용자로 위장하여 로그인한 것처럼 보이는 등의 공격이 가능하다

  • 쿠키 스니핑(sniffing): 악의적인 공격자가 네트워크 트래픽을 감시하여 쿠키 데이터를 훔쳐갈 수 있다. 특히 공용 Wi-Fi 네트워크를 사용하는 경우 데이터 보안이 약화될 수 있다

  • XSS(Cross-Site Scripting) 공격: 쿠키는 자바스크립트로 읽고 쓸 수 있는 데이터라 악의적인 사용자가 사이트에 악의적인 스크립트를 삽입하여 다른 사용자의 쿠키를 훔쳐갈 수 있는 공격이 발생할 수 있다

  • 쿠키 캐시: 일부 브라우저에서는 쿠키를 캐시하여 저장하므로, 사용자가 로그아웃해도 브라우저에 쿠키가 남아있어 로그인 상태가 유지될 수 있다.

 쿠키 옵션

쿠키는 최대 용량으로 약 4KB를 가지고, 키-값의 데이터와 옵션으로 pathdomainexpires/max-agesecure를 설정할 수 있다

Path

path=/mypath

path 옵션을 지정한 경우, 지정한 경로나 지정한 경로의 하위 경로에 있는 페이지만 쿠키에 접근 가능하다.

기본값은 현재 경로이다

domain

domain=site.com

쿠키에 접근 가능한 도메인을 지정한다. domain 옵션을 지정하지 않은 경우, 쿠키를 설정한 도메인을 제외하고 외부 도메인이나 서브 도메인에서 쿠키 정보를 얻을 수 없다

이런 제약사항은 안정성을 높이기 위함

expires/max-age

expires=Tue, 19 Jan 2038 03:14:07 GMT

max-age=3600

이 속성을 설정한 쿠키는 persistent cookie이다
위 두 옵션을 설정하지 않으면, 브라우저가 닫힐 때 쿠키가 삭제된다. 이러한 쿠키를 Session Cookie라 한다

Persistent cookie
브라우저를 닫아도 쿠키의 만료시간까지는 유지되어서, 해당 시간이 지나기 전까지는 브라우저에서 계속 유지된다

Session cookie
웹 서버에서 클라이언트로 보내는 쿠키 중 하나로, 사용자가 웹 사이트에 로그인하고 해당 사용자의 상태를 추적하기 위해 사용된다.
일반적으로 웹 서버는 클라이언트의 브라우저에 session ID를 포함한 쿠키를 보내고, 클라이언트는 이 쿠키를 저장하고, 이후 서버와의 통신 시 이 쿠키를 함께 전송한다
웹 서버는 session ID를 사용하여 해당 사용자의 세션 상태를 추적하며, 해당 세션 상태에 대한 정보를 저장할 수 있다. 이러한 정보에는 로그인 상태, 장바구니 내용 등이 포함된다
브라우저가 종료될 때까지 유지되며, 일반적으로 보안적인 이유로 HTTPOnly 속성이 설정되어있다. 이는 JavaScript 등을 통해 쿠키에 접근하는 것을 막아 쿠키의 안전성을 높이기 위함이다

secure

secure 옵션의 경우 설정 시 HTTPS 프로토콜로 통신하는 경우에만 쿠키가 전송됨
secure 옵션이 없으면, HTTP 프로토콜과 HTTPS 프로토콜 통신 모두 쿠키가 전송

httpOnly

웹서버에서 Set-Cookie 헤더를 이용해 쿠키를 설정할 때 지정할 수 있다
이 옵션은 자바스크립트 같은 클라이언트 측 스크립트가 쿠키를 사용할 수 없게 한다
document.cookie를 통해 쿠키를 볼 수도 없고 조작할 수도 없다
해커가 악의적인 자바스크립트 코드를 페이지에 삽입하고 사용자가 그 페이지에 접속하기를 기다리는 방식의 공격을 예방할 때 이 옵션을 사용한다

한편, 쿠키는 JavaScript로 접근이 불가능하다. 그래서 localStorage만큼 XSS 공격에 취약하지 않다고 한다
만약 공격자가 JavaScript를 특정 사이트에서 실행한다고 했을 때, cookie의 httpOnly나 secure 옵션을 사용한다면 우리의 쿠키는 JavaScript의 접근에 안전해진다고 한다

사용예시

  1. 방문 사이트에서 로그인 시, "아이디와 비밀번호를 저장하시겠습니까?"
  2. 팝업창을 통해 "오늘 이 창을 다시 보지 않기" 체크

    사용자가 팝업창에서 "오늘 이 창을 다시 보지 않기"를 체크하고 팝업을 닫으면, 웹 사이트는 이 정보를 쿠키에 저장하고 사용자가 같은 웹 사이트를 방문할 때마다 브라우저는 해당 쿠키를 읽어와 "오늘 이 창을 다시 보지 않기" 설정을 확인하는 과정으로 진행된다고 한다

세션(Session)

일정 시간 동안 같은 사용자(브라우저)로부터 들어오는 일련의 요구를 하나의 상태로 보고, 그 상태를 유지시키는 기술이다.

여기서 일정 시간은 방문자가 웹 브라우저를 통해 웹 서버에 접속한 시점부터 웹 브라우저를 종료하여 연결을 끝내는 시점을 말한다.

즉, 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 한다.

세션은 서버에 저장된 정보

이는 로그인을 이용해 쉽게 설명이 가능하다.
사용자가 사용자 정보를 입력하여 로그인을 시도하면 서버는 사용자 정보를 데이터베이스에 존재하는지 확인한 후 사용자 정보에 대한 세션을 세션 저장소에 저장한다
이렇게 만들어진 세션에 접근하기 위한 열쇠로써 Session ID를 발급한다. 이후 서버는 Session ID를 쿠키에 담아 클라이언트 측으로 보낸다. 여기서 사용되는 쿠키는 일반적으로 expires/max-age 옵션을 지정하지 않은 Session Cookie(브라우저 종료 시 삭제되는 쿠키)이다
즉, 클라이언트 측은 브라우저가 종료될 때까지 Session ID를 지니고, 요청마다 Session ID가 담긴 쿠키를 서버로 보낸다. 서버는 사용자 정보를 데이터베이스에서 확인할 필요 없이 세션 저장소에서 쿠키를 검증하여 유저 정보를 획득하고 이를 클라이언트에게 보내 로그인 상태를 유지한다

세션특징

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

세션과정

  1. 클라이언트가 페이지에 요청한다. (사용자가 웹사이트에 접근)
  2. 서버는 접근한 클라이언트의 http 요청 헤더의 Cookie를 확인하여, 클라이언트가 해당 session-id를 보냈는지 확인한다.
  3. session-id가 존재하지 않는다면 서버는 session-id를 생성해 클라이언트에게 돌려준다.
  4. 서버에서 클라이언트로 돌려준 session-id를 쿠키를 사용해 서버에 저장한다.
  5. 클라이언트는 재접속 시, 이 쿠키를 이용해 session-id 값을 서버에 전달

세션전달과정

사용예시

화면을 이동해도 로그인이 풀리지 않고 로그아웃하기 전까지 유지

사용자가 웹 사이트에 접속하고 로그인하면, 서버는 사용자에 대한 정보를 가지고 있는 세션을 생성한다.세션을 사용하면 사용자가 로그인한 상태에서 화면을 이동하거나 작업을 수행해도 로그인 상태가 유지된다. 이것은 서버가 사용자에 대한 정보를 기억하고 있기 때문이다. 사용자가 로그아웃하거나 세션이 만료되면, 서버는 해당 세션에 저장된 정보를 삭제한다. 이렇게 로그인이 유지된다
즉 세션은 서버가 사용자의 상태와 정보를 임시로 기억하는 방법이다. 이를 통해 사용자는 로그인 상태를 유지하면서 웹 사이트를 사용할 수 있게 된다. 개발자가 이 세션을 관리하여 로그인, 로그아웃 등의 상태를 유지하고 처리한다.

쿠키와 세션 비교

쿠키와 세션은 비슷한 역할을 하며, 동작 원리도 비슷하다. 그 이유는 세션도 결국 쿠키를 사용하기 때문

  1. 사용자의 정보가 저장되는 위치
    쿠키는 서버의 자원을 전혀 사용하지 않으며, 세션은 서버의 자원을 사용한다.

  2. 보안
    쿠키는 클라이언트 로컬에 저장되기 때문에 변질되거나 request에서 스니핑 당할 우려가 있어서 보안에 취약하지만 세션은 쿠키를 이용해서 session-id만 저장하고 그것으로 구분하여 서버에서 처리하기 때문에 비교적 보안성이 높다.

    XSS(Cross-Site Scripting) 공격
    XSS 공격은 자바스크립트가 사용자의 컴퓨터에서 실행된다는 점을 이용한 공격
    자바스크립트에서 "document.cookie"라는 명령어는 사이트에서 쿠키 값을 활용할 수 있게 하는 역할을 하지만 공격자들은 쿠키 값을 탈취하기 위해서 사용할 수 있다

    HttpOnly라는 옵션을 통해 아래와 같이 쿠키탈취 방지

스니핑 공격(Sniffing)
네트워크 상에 전달되는 쿠키가 스니핑 공격에 의해서 탈취당할 수 있습니다

  1. 만료시간(라이프사이클)
    쿠키의 경우 브라우저 측에서 만료 기간을 설정하여 일정 기간 동안 유지되며, 세션은 서버 측에서 만료 기간을 설정하여 사용자의 활동 여부에 따라 유지되다가 만료되거나 서버에서 삭제된다.

  2. 속도
    쿠키는 쿠키에 정보가 있기 때문에 서버에 요청 시 속도가 빠르고
    세션은 정보가 서버에 있기 때문에 처리가 요구되어 비교적 느린 속도를 낸다.

JWT(Json Web Token)

인증 및 정보 교환을 위한 토큰 기반의 개방형 표준
세션과 다르게 사용자들의 상태를 저장할 필요가 없이 요청이 들어올때마다 서버의 비밀값으로 유저의 일치여부를 판단할 수 있다

JWT 의 취약점

한편 JWT는 이미 줘버린 토큰을 빼앗을 수도 없고 그 토큰의 발급 내역이나 정보를 서버에서 기록하여 통제하고 있지 않기 때문에 여러명의 사용자의 로그인 상태를 완벽하게 관리하기에는 그 자체로는 어렵다

그럼 JWT 는 못쓰는 것인가?

아니다. 이 문제를 해결하기 위해서는 토큰 2개를 주면된다.
이 두개의 토큰은 각각 몇시간, 몇분 이하로 짧은 엑세스토큰과 2주정도 긴 수명을 갖는 리프레시 토큰이다

쿠키, 세션, JWT 는 각각 언제 사용해야할까?(*0819 추가)

나도 모르는 사이에 인증방법을 검색하면 토큰, 그 중에서도 JWT 를 활용한 인증방법에 관한 자료가 하도 많이 나와서 토큰 기반으로 인증을 진행하였다.
하지만 우연히 좋은 기회로 현업자 분께 강의를 들었는데 그 분이 하신 말씀이 인상깊어 기록해보고자 한다

쿠키는 보안상의 위협이 크다

쿠키는 요청(request)에서 탈취당할 우려가 크다

세션의 경우 쿠키의 보안상의 위협을 방지하고 서버가 인증정보를 관리한다

세션은 쿠키에 세션ID만 저장하고 서버에서 처리하기 때문에 보안상 더 우수하다.

토큰인증방식의 경우 모바일이 아닐 경우, 대규모 트래픽을 다루지 않을 경우 권장되지 않는다

백엔드의 관점에서는 토큰인증방식의 장점은 아래와 같다

  1. 토큰에는 사용자 정보가 있다
  2. 인증을 위해서 인증 서버를 찌를 필요가 없고 토큰만 해석하면된다. 따라서 이 경우 대규모 트래픽에 유리하다

이것이 세션과는 다른 토큰의 장점이다

그러나 토큰방식에도 단점이 있다

토큰탈취가 그 예이다
인증정보를 주고받을 때 보통 public 와이파이망을 사용한다. 요청을 주고받는 과정에서 네트워크망을 탈취한다면 토큰은 바로 탈취되어 의도하지 않은 동작을 일으킬 수 있다

따라서 대규모 트래픽의 서비스가 아니라면 세션인증방식을 추천하고, 세션인증방식의 경우 서버 부하를 고려해 세션저장소를 기존 저장소 밖에 만들어서 인증정보를 관리하는 방식이 웹 환경에서는 보편적이라고 한다.

모바일 환경에서는 세션과 쿠키의 이용이 웹보다 어렵기에 토큰을 사용한다고 한다.
따라서 멀티 클라이언트 환경에서는 토큰이 권장된다고 한다

대규모 트래픽을 다룰 경우 토큰은 이렇게 활용하자!(*0830 추가)

access token 과 refresh token 을 이용하고 토큰 시간을 짧게 가져가고, 모든 구간에 https 를 반드시 쓰는 규칙을 통해 토큰 탈취를 막을 수 있다.

위의 정보를 토대로 아래의 방식을 통해 우리는 프론트엔드와 백엔드에서 토큰을 안전하게 주고 받을 수 있다라고 생각한다.

  1. [프론트엔드] ID와 비밀번호를 준다.
  2. [백엔드] ID와 비밀번호를 검증하고 AccessToken, RefreshToken을 반환한다. 이 때 AccessToken의 만료시간을 설정한다.
    RefreshToken의 경우 DB에 {ID, RefreshToken} 식으로 저장한다.
  3. [프론트엔드] AccessToken을 받아 다음 api호출부터 헤더에 붙여준다. RefreshToken은 안전한 곳에 보관한다.
  4. [백엔드] api호출시 AccessToken이 유효한지, 만료시간이 지나지 않았는지 확인하여 처리한다.
  5. [프론트엔드] 만약 AccessToken이 만료되어 api 동작이 실패하였다면, RefreshToken을 백엔드에 줘서 Reissue를 건다.

    이 때 리프레시 토큰을 쿠키에 httpOnly 옵션을 사용해서 https 로 암호화해서 전달하면 탈취 위험성이 적다

  6. [백엔드] Reissue요청이 오면, RefreshToken이 DB에 있는 것과 같은지 비교하고, 맞다면 AccessToken을새로 만들어 반환한다.

https://heavenlake.tistory.com/114

쿠키(Cookie)와 세션(Session)의 차이 (+캐시(Cache))
https://80000coding.oopy.io/1f213f10-185c-4b4e-8372-119402fecdd0

profile
기록용

0개의 댓글