11. 클라이언트 식별과 쿠키

11.1 개별 접촉

HTTP의 특징

  1. 익명이다.

  2. 상태가 없다.

  3. 요청과 응답으로 통신한다.

(1) 사용자를 식별하거나, (2) 연속적인 요청을 추적하기 위해서는, 약간의 정보가 필요하다.

개인화 예

  • 개별 인사 (ex. 우빈 님, 안녕하세요?)

  • 사용자 맞춤 추천

  • 주소, 신용카드 정보 입력 자동화 (cf. DB에 저장하기도 함)

  • 세션 추적 (ex. 장바구니)

11.2 HTTP 헤더

11.3 클라이언트 IP 주소

  • 사용자 식별에 클라이언트 IP 주소 사용 (ex. 인트라넷에서 특정 IP 주소에만 응답)

  • 보통 HTTP 헤더에 IP 주소가 들어가지는 않음

  • 웹 서버 HTTP 요청을 보내 반대쪽 TCP 커넥션의 IP 주소를 알아냄

IP 주소의 문제점

  1. IP 주소는 사용자가 아니라 컴퓨터를 가리킨다. 여러 사용자가 같은 컴퓨터를 사용할 수 있다.

  2. ISP는 동적으로 IP 주소를 할당한다.

  3. 많은 사용자가 NAT 방화벽을 통해 인터넷을 사용한다. NAT 장비들은 클라이언트들의 실제 IP 주소를 하나의 방화벽 IP 주소로 변환한다.

  4. 서버가 프락시나 게이트웨이와 연결되어 있는 경우, 서버는 클라이언트의 IP 주소 대신 프락시의 IP 주소를 본다. (프락시 확장 헤더(Client-ip, X-Forwarded-For)를 사용할 수도 있지만 모든 프락시가 그렇게 하지는 않는다.)

11.4 사용자 로그인

  1. 클라이언트가 요청

  2. 서버는 401 Login Required 응답과 WWW-Authenticate 헤더를 반환해 로그인 요청

  3. 사용자가 입력한 로그인 정보 토큰 Authorization 헤더에 담아 보냄 (ex. Authorization: Basic am910jRmdW4=)

  4. 추후 요청에 대해서는 서버가 요청하지 않아도 사용자 이름과 비밀번호를 포함해 전달해 세션이 진행되는 내내 사용자에 대한 식별을 유지함

사용자 로그인의 문제점

  • 모든 사이트에 로그인하는 게 귀찮음

  • 서로 다른 사용자 이름과 비밀번호를 기억해야 함

11.5 뚱뚱한 URL

  1. 사용자가 처음 방문하면 유일한 ID가 생성됨

  2. URL 처음이나 끝에 ID를 추가함 ex. http://amazon.com/.../002-1145265-801683

  3. 서버가 ID를 포함한 요청을 받으면 사용자와 관련된 추가적인 정보(ex. 장바구니, 프로필)를 찾고, 응답을 뚱뚱한 URL로 만듦

뚱뚱한 URL의 문제점

  • URL이 못생겨서 사용자 혼란

  • 공유 불가: 공유하면 뚱뚱한 URL에 담긴 개인정보가 같이 공유됨

  • 캐시 접근 불가: URL이 계속 달라지기 때문에 캐시를 사용할 수 없음

  • 서버 부하 증가: 뚱뚱한 URL에 해당하는 각 페이지들을 새로 그려야 함

  • 세션 지속 불가: 사용자가 뚱뚱한 URL을 북마크하지 않는 이상 로그아웃하면 모든 정보를 잃음

  • 사용자가 세션에서 이탈하기 쉬움

11.6 쿠키

쿠키

  • 사용자를 식별하고 세션을 유지하는 방식 중 가장 널리 사용됨

  • 새로운 HTTP 헤더를 정의함

  • 쿠키와 캐시가 충돌할 수 있어서 쿠키의 내용물은 캐싱하지 않음

11.6.1 쿠키의 타입

우빈: "discard 파라미터가 포함되어 있으면 세션 쿠키다"라는 내용은 2000년에 작성 RFC 2965에 정의되어 있으나, 현재 이 문서는 RFC 6265에 의해 대체되었으며 더이상 쓰이지 않는 것으로 생각됩니다. 이 책은 정말 오래되었군요!

11.6.2 쿠키는 어떻게 동작하는가

  1. 사용자가 웹 서버를 방문한다. 서버는 사용자에 대해 아무 것도 모른다.

  2. 서버는 사용자를 식별하기 위한 값을 쿠키에 할당한다.

    • 쿠키는 이름=값 형태의 리스트이다.

    • 서버는 이 리스트를 Set-Cookie 헤더에 담아 클라이언트에 전달한다.

  3. 브라우저는 서버에서 온 Set-Cookie 헤더에 있는 쿠키를 데이터베이스에 저장한다.

  4. 사용자가 나중에 같은 사이트를 방문하면 브라우저는 Cookie 헤더에 쿠키를 담아 전송한다.

우빈: Set-Cookie2 역시 RFC 2965에 따라 현재는 폐기되었습니다.

11.6.3 쿠키 상자: 클라이언트 측 상태

  • 클라이언트 측 상태: 브라우저가 쿠키 정보를 저장하는 시스템

  • 공식적으로는 HTTP 상태 관리 체계 (HTTP State Management Mechanism) 라고 불림

우빈: RFC 2965 문서 이름이랑 같아요.

구글 크롬 쿠키

크롬은 Cookies라는 SQLite 파일에 쿠키를 저장한다.

우빈: 구글 크롬 쿠키를 직접 확인해 봅시다! [개발자 도구(F12)] - [Application] - [Storage] - [Cookie].

책에 있는 필드 설명은 좀 오래 되었습니다. 공식 문서에서 확인해 보세요.

RFC6265bis: SameSite (experimental) 같은 사이트에서 왔을 때와 아닐 때 어떻게 쿠키 처리를 할지 알려줌. (SameSite cookies explained)

마이크로소프트 인터넷 익스플로러 쿠키

우빈: 2020년대에는 인터넷 익스플로러 같은 걸 사용하는 사람이 없길 바라며 생략합니다.

11.6.4 사이트마다 각기 다른 쿠키들

  • 브라우저는 각 사이트에 모든 쿠키를 보내지 않는다.

  • 보통 브라우저는 쿠키를 생성한 서버에게만 해당 쿠키 전달한다.

  • 쿠키를 모두 전달하면 성능이 저하된다. 콘텐츠보다 쿠키 바이트가 더 클 수 있다.

  • 쿠키의 이름=값 쌍들은 특정 서버에만 특화된 것으로 다른 사이트에서는 무의미한 값이다.

  • 쿠키를 모두 전송하면 특정 사이트에서 만든 쿠키를 신뢰하지 않는 사이트로 보 개인정보 문제가 생길 수 있다.

쿠키의 속성

서버는 쿠키를 생성할 때 Set-Cookie 응답 헤더에 여러 속성을 넣어 쿠키를 제어한다.

ex.

Set-cookie: user="woobin"; domain="google.com"
Set-cookie: pref="florida project"; domain="google.com"; path="/movie/"
  1. Domain: 어떤 사이트가 그 쿠키를 읽을 수 있는지 제어한다.

  2. Path: 해당 경로에 속하는 페이지에만 쿠키를 전달한다.

ex. 광고 회사

  • 광고는 웹사이트의 일부인 것처럼 보이지만, 실제로는 광고를 관리하는 광고사 서버의 것이다.

  • 광고에 관련 쿠키 광고사 서버에서 만든 지속 쿠키이다. 즉, 해당 쿠키의 도메인은 광고 회사로 설정되어 있다.

  • 사용자가 A 사이트에서 B 사이트로 옮겨 가도 브라우저는 같은 지속 쿠키를 광고사 서버에 전송할 수 있다.

11.6.5 쿠키 구성요소

현재 사용되는 쿠키 명세는 RFC 6265이다. 이 책에서는 현재 쓰이지 않는 Version 0 쿠키(넷스케이프 쿠키), Version 1 쿠키(RFC 2965)를 다룬다.

11.6.6 Version 0(넷스케이프) 쿠키

  1. 형식

Set-cookie: name=value [; expires=date] [; path=path] [; domain=domain] [; secure]
Cookie: name1=value1 [; name2=value]
  1. (서버) Version 0 Set-Cookie 헤더

11.6.7 Version 1 (RFC 2965) 쿠키

Version 0 쿠키와의 차이점

  • 쿠키마다 목적을 설명하는 설명문이 있다.

  • 만료 주기와 상관없이 브라우저가 닫힐 때 쿠키를 삭제할 수 있다.

  • 절대 날짜(Expires) 대신 초 단위의 상대 값(Max-age)으로 쿠키의 생명주기를 결정한다.

  • 포트 번호로도 쿠키를 제어한다.

  • 버전 번호가 추가되었다.

  • Cookie 헤더에 $ 접두어가 있다.

  • (서버) Version 1 Set-Cookie2 헤더

  1. Version 1 Cookie 헤더

  2. Set-Cookie2 필터 중에서 현재의 웹 사이트에 들어맞는 들어맞는 필터 정보에 달러 문자($)를 붙여서 전송한다.

  3. 클라이언트가 Cookie2 헤더를 보내고, 서버가 이를 인식할 수 있으면, 서버는 Set-Cookie2 헤더를 보내야 한다.

  4. 클라이언트가 같은 쿠키를 Set-Cookie와 Set-Cookie2에서 모두 받으면 Set-Cookie는 무시한다.

  5. 클라이언트가 Version 0 Version 1을 모두 지원하더라도, 서버가 Set-Cookie를 보내면 클라이언트는 Cookie 헤더를 보내야 한다. 단 Cookie2: $Version="1"을 같이 보내 업그레이드할 수 있음을 알린다.

11.6.8 쿠키와 세션 추적

세션 쿠키를 사용해 사용자의 연속적인 트랜잭션을 추적한다. (아래의 그림에서는 뚱뚱한 URL도 함께 사용한다.)

11.6.9 쿠키와 캐싱

쿠키와 관련된 문서를 캐싱하면 사용자의 쿠키가 다른 사용자에게 할당되거나, 개인 정보가 노출될 수 있다.

  • Set-Cookie 빼고 캐시를 해도 된다면, 명시적으로 Cache-Control: no-cache="Set-Cookie"를 표시한다.

  • 캐시를 해도 되는 문서에는 Cache-Control: public을 사용한다.

  • (서버의 응답에) 어떤 캐시는 Set-Cookie 헤더를 제거한다.

    • 캐시가 모든 요청마다 원 서버에 재검사하도록 만들 수 있다.

    • 재검사를 위해 Cache-Control: must-revalidate, max-age=0을 추가한다.

  • 더 보수적인 캐시는 Set-Cookie를 가지고 있는 응답은 아예 캐싱하지 않는다.

  • (클라이언트의 요청에서) 보수적인 캐시는 Cookie 헤더가 있는 요청에 대한 응답은 캐시하지 않는다.

    • 이미지는 캐싱하고 텍스트는 캐싱하지 않을 수도 있다.

    • 이미지에 Max-age가 0인 Cookie 헤더를 설정해 매번 재검사하게 만들 수 있다.

11.6.10 쿠키, 보안, 그리고 개인정보

쿠키 자체가 보안상으로 엄청 위험한 건 아니다.

tl; dr CIAC I-034 인터넷 쿠키: 쿠키의 위험성이 과대평가되었다는 평가서

  • 원격 DB에 정보를 저장하고 데이터의 키 값을 쿠키에 저장하는 방식을 표준으로 사용하면 데이터가 서버와 클라 사이에 직접 오가지 않는다.

  • 다만 광고 웹 사이트가 사용자를 추적하기 위해 지속 쿠키를 사용하는 것과 같은 오용은 조심하자.

Last updated