[네트워크] Cookie, Session, JWT

Updated: Categories:

여러가지 인증 전략에 대해 알아보자

  • Stateless한 HTTP의 단점을 해소하고자 사용
  • 브라우저에 저장되어있는 key-value 형태의 데이터
  • 브라우저가 종료되어도 쿠키는 유지됨
  • expire 시간을 설정할 수 있음
  • 브라우저에 총 300개의 쿠키 저장 가능
    • 하나의 도메인당 20개 저장 가능
    • 쿠키 하나당 4KB까지 저장 가능
  • 응답 HTTP에 Set-Cookie 헤더를 추가하면 쿠키를 만들 수 있음
  • 브라우저에서 자동으로 요청 HTTP 헤더에 쿠키를 추가함

구성 요소

  • 이름(Name) : 각각의 쿠키를 구별하는 데 사용되는 이름
  • 값(Value) : 쿠키의 이름과 관련된 값
  • 유효시간(Expires) : 쿠키의 유지시간
  • 도메인(Domain): 쿠키를 전송할 도메인
  • 경로(Path): 쿠키를 전송할 요청 경로

Local/Session Storage

  • HTML5에서 추가된 브라우저 저장소
  • 하나의 도메인에서 하나의 로컬 스토리지를 가짐
  • 브라우저에서 요청할때 HTTP 헤더에 자동으로 쿠키를 추가하는데…
    • 만약 필요없는 정보까지 저장되어 쿠키 용량이 커진다면 요청의 크기가 계속 커지게 됨
    • 따라서 굳이 보낼 필요없는 데이터는 Local Storage 및 Session Storage에 저장함
  • Local Storage는 영구저장, Session Storage는 브라우저가 꺼지면 삭제됨

단점

  • 용량이 작음 (최대 4KB)
  • 매 HTTP 요청마다 포함되어 데이터가 커질경우 서버에 부담을 줌
  • 평문으로 되어있어 보안에 취약함


Session

  • 쿠키를 사용하며, 사용자 정보를 서버에서 관리하는 방식
    • 쿠키를 사용하므로 만료시간 설정 가능
  • 브라우저가 종료되면 세션이 만료됨

동작원리

  1. 클라이언트 인증요청
    1. 서버에서 세션ID 발급 -> 저장소에 세션ID와 사용자 데이터를 저장
    2. 발급한 세션ID를 쿠키에 담아 응답
  2. 클라이언트는 세션ID가 담긴 쿠키를 헤더에 담아 서버에 요청
    1. 서버는 세션ID를 보고 세션저장소에서 찾음
    2. 세션ID에 매핑된 사용자 데이터를 조회하고 응답

장점

  • 사용자 정보를 클라이언트에 저장해야하는 단일 쿠키 방식보다 보안에 유리함
    • 쿠키에는 세션ID만 저장하기때문에 탈취당해도 타격없음

단점

  • 사용자가 많아질수록 서버 메모리를 많이 차지함
  • 접속시마다 세션을 발급하고, 계속 관리해함
    • 동접자가 많아질수록 서버에 과부하를 일으킴

세션 분리

  • 만약 세션정보를 서버 인메모리로 관리한다고 했을때 서버를 껐다 키면?
    • 사용자의 세션정보는 브라우저 쿠키에 저장되어 있지만…
    • 서버에서 해당 세션이 유실되어서 다시 발급해야함
  • 세션 저장소의 위치를 서버와 분리에 외부에 둠
    • 세션을 인메모리가 아닌 외부 스토리지에 저장한다 (보통 가벼운 인메모리 DB를 사용. Redis)

Session Cluster

  • 세션 저장소가 만약 하나라면 해당 저장소에 문제가 발생했을 때 모든 세션이 날아가게됨
    • 따라서 세션 저장소를 물리적으로 여러개 두고, 모두가 동일한 상태를 유지하도록 함 (일관성)
  • Sticky Connection(동일한 사용자가 발생시킨 요청은 동일한 WAS에서 처리됨을 보장) 제약에서 자유로움


JWT (Json Web Token)

  • 사용자 정보를 암호화시킨 토큰에 저장하는 방법
  • URL-Safe 텍스트로 구성되기 때문에 HTTP 프로토콜의 어느 위치에든 들어갈 수 있음
    • 보통 HTTP 헤더에 넣음
  • json 포맷을 사용하여 데이터를 저장

구성요소

  • Base64 Url-Safe 방식으로 인코딩
    • dot(.)을 구분자로 결합함
  • Header, Payload, Signature 세 부분으로 구성됨
  • Header
    • Header는 두가지 종류의 key값을 가진다
      • typ : 토큰 타입
      • alg : 암호화 알고리즘 방식 / Signature에 사용 (HMAC, RSA 지원)
  • Payload
    • JWT를 통해 전달하고자 하는 데이터, Claim-Set 이라고 함
    • JWT 자체는 암호화된것이 아닌 인코딩된것이므로 민감정보를 포함하면 안된다.
    • 세가지 종류의 Claim으로 구분된다
      • Public Claims : 사용자 정의 클레임 / 공개용 정보를 저장 (충돌 방지를 위해 URI 포맷 사용)
      • Private Claims : 사용자 정의 클레임 / 사용자 정보를 저장
      • Registered Claims : 미리 등록된 클레임 / 필수적으로 사용할 필요는 없지만 사용을 권고함
        • iss : 토큰을 발급한 발급자 (Issuer)
        • exp : 만료시간이 지난 토큰은 사용불가
        • nbf : Not Before의 의미로 해당 시간 이전에는 토큰 사용불가
        • iat : 토큰이 발급된 시각
        • jti : JWT ID로 토큰에 대한 식별자
  • Signature
    • 토큰이 위변조되지 않았음을 증명함
    • Header 인코딩값 + Payload 인코딩값 -> 비밀키(secret)으로 해싱 -> base64 인코딩

동작원리

  1. 클라이언트 인증요청
  2. 서버에서 요청 검증 후 JWT 반환
  3. 사용자의 브라우저에서 해당 JWT를 저장하고 매 요청시마다 HTTP 헤더에 JWT를 넣어서 보냄
  4. 서버는 매번 JWT 유효성 검사 후 요청 수락

장점

  • Stateless 상태를 지향하는 Rest API에서 적합
  • 클라이언트가 정보를 가지고 있기에 세션처럼 별도의 저장소가 필요하지 않음

단점

  • 세션보다는 보안 취약
    • 세션이 탈취당하면? : 해당 세션을 삭제해버리면 됨
    • JWT가 탈취당하면? : JWT 유효기간이 끝날때까지 사용가능
      • 따라서 유효기간을 짧게주고 Refresh Token을 사용한다.
  • 다중 로그인 컨트롤, 사용자 유효성 체크, 강제 로그아웃 기능 구현이 어려움