[11장] 클라이언트 식별과 쿠키

janjanee·2022년 8월 1일
0
post-thumbnail

2020.12.13 작성글 이전


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

11.1 개별 접촉

현대의 웹 사이트들은 개인화된 서비스를 제공하고 싶어한다. 네트워크로 연결된 사용자들에 대해 더 많이 알고 싶어하고 사용자들의 검색 내용 등을 기록하고 싶어한다. 그러한 내용을 바탕으로 사이트를 개인화시켜서 사용자에게 제공한다.

  • 개별 인사

    개인에게 맞춰져 있는 것 처럼 보이기 위해서 사용자 특화 환영 메시지 혹은 페이지 내용을 만든다.

  • 사용자 맞춤 추천

    고객의 생일이나 특별한 날에 고객의 흥미에 따라 특별한 제품을 추천하기도 한다.

  • 저장된 사용 정보

    우리들은 쇼핑을 할 때 주소나 신용카드 정보를 매번 입력하기 귀찮아 한다. 이런 정보를 데이터베이스에 저장하여, 식별된 사용자는 더 이상 정보를 입력하지 않고 편리하게 사용할 수 있다.

  • 세션 추적

    HTTP 트랜젝션은 상태가 없다. 많은 웹사이트에서 사용자가 사이트와 상호작용할 수 있게 사용자의 상태를 남긴다.(장바구니 기능) 상태를 유지하기 위해서, 웹 사이트는 사용자에게서 오는 HTTP 트랜젝션을 식별할 방법이 필요하다.

이 장은 HTTP가 사용자를 식별하는 데 사용하는 기술을 정리한다.

11.2 HTTP 헤더

헤더 이름헤더 타입설명
From요청사용자의 이메일 주소
User-Agent요청사용자의 브라우저
Referer요청사용자가 현재 링크를 타고 온 근원 페이지
Authorization요청사용자 이름과 비밀번호
Client-ip확장(요청)클라이언트의 IP 주소
X-Forwarded-For확장(요청)클라이언트의 IP 주소
Cookie확장(요청)서버가 생성한 ID 라벨

위의 표는 가장 일반적인 일곱 가지 HTTP 요청헤더이다. 우선 앞의 3개 (From, User-Agent, Referer)를 살펴본다.

  • From : 사용자의 이메일 주소를 포함한다.

    악의적인 목적으로 사용자들의 이메일 주소를 모아 스팸메일 발송 등의 문제가 있어서 From 헤더를

    보내는 브라우저는 많지 않다.

  • User-Agent : 사용자가 사용하고 있는 브라우저의 이름 과 버전정보, 운영체제에 대한 정보를 보낸다.

    보통 특정 브라우저에서 제대로 동작할 수 있도록 콘텐츠를 최적하하는데 유용하다.

    사용자 식별에는 도움이 되지 않음.

  • Referer : 사용자가 현재 페이지로 유입하게 한 이전 웹페이지 URL을 가리킨다.

    사용자를 식별할 수는 없지만, 사용자가 이전에 어떤 페이지를 방문했는지를 알아내어

    사용자의 웹 사용 행태나 취향을 파악할 수 있다.

위의 3개 헤더들은 사용자 정보를 확실하게 식별하기에는 부족해 보인다. 바로 다음에 이어서 더 자세히 특정 사용자를 식별하는 방법들을 소개한다.

11.3 클라이언트 IP 주소

초기의 웹 선구자들은 사용자 식별에 클라이언트의 IP 주소를 사용하려 헀다. 그러나 안타깝게도 클라이언트 IP 주소로 사용자 식별하는 방식은 몇 개의 문제점이 존재한다.

  • 여러 사용자가 한 대의 컴퓨터를 사용한다면 하나의 IP로 어떤 사용자인지 식별할 수 없다.

  • 인터넷 서비스 제공자(ISP)는 사용자가 로그인하면 동적으로 IP 주소를 할당한다.

    매번 다른 주소를 받으므로 식별할 수 없다.

  • 네트워크 주소 변환(Network Address Translation, NAT) 방화벽을 통해 인터넷을 사용할 경우,

    NAT 장비는 실제 IP 주소를 방화벽 뒤로 숨기고, 내부에서 사용하는 하나의 방화벽 IP 주소(다른 포트번호)로 변환한다.

  • HTTP 프락시와 게이트웨이는 원 서버에 새로운 TCP 연결을 한다.

    웹 서버는 클라이언트의 IP 대신 프락시 서버의 IP 주소를 보게된다.

위의 문제점들로 인해 이 방식은 제대로 동작하지 않는다. 인트라넷 같이 제한된 영역내에서는 적절해 보일 수 있지만, 인터넷에서는 IP 주소를 임의로 변경할 수 있기 때문에 문제가 발생할 수 있다.

11.4 사용자 로그인

웹 서버는 사용자 이름과 비밀번호로 인증(로그인) 할 것을 요구해서 사용자에게 명시적으로 식별 요청을 할 수 있다.

  • (A)에서 브라우저는 www.google.com 사이트로 요청한다.

  • 사이트는 사용자 식별정보를 알지 못하므로, (B)와 같이 401 Login Required HTTP 응답코드

    WWW-Authenticate 헤더를 반환하여 로그인 하라고 요청한다. (브라우저에 로그인 창 띄움)

  • 사용자가 이름과 비밀번호를 입력하고, 브라우저는 기존요청을 다시 보내서 사용자 식별을 시도한다.

  • 이제 서버는 사용자 식별정보를 안다.

  • 이 시점 이후 요청에 대해서, 브라우저는 서버에게 사용자 식별정보를 Authorization 헤더에 담아 전송한다.

하지만, 웹 사이트 로그인은 매우 귀찮은 일이다. 사이트를 옮겨다닐 때 마다 해당 사이트에 로그인을 해야한다. 또한, 사이트 마다 정보가 다를 수 있으며 그 정보를 사용자가 모두 기억해야 한다.
사용자는 급기야 인터넷 사용을 포기할 수도 있다...😞

11.5 뚱뚱한 URL

어떤 웹 사이트는 사용자의 URL마다 버전을 기술하여 사용자를 식별하고 추적하였다. URL 경로의 처음이나 끝에 어떤 상태정보를 추가해 확장한다.

사용자의 상태 정보를 포함하고 있는 URL을 뚱뚱한 URL이라고 한다.

<a href="/exec/obidos/002-1234567-333">All Gifts</a>
<a href="/exec/wishlist/ref=gr_pp/002-1234567-333">Wish List</a>

'002-1234567-333' 정보가 사용자에게 할당된 식별번호며, 이 번호를 각 URL 뒤에 붙여 사용자를 추적한다.

사용자가 처음 웹 사이트에 방문하면 유일한 ID가 생성되고, 이 값은 URL에 추가되며
서버는 클라이언트를 이 뚱뚱한 URL로 리다이렉트 시킨다.

그런데 이 기술에는 심각한 문제 몇 가지가 있다.

  • 못생긴 URL

    브라우저에 보이는 이 뚱뚱하고 못생긴 URL은 사용자에게 혼란을 준다.

  • 공유하지 못하는 URL

    특정 사용자와 세션에 대한 정보를 포함하기 때문에, 그 주소를 누군가에게 공유하면 누적된 개인정보를 타인에게 공유하게 되는 것이다.

  • 캐시를 사용할 수 없음

    URL로 만드는 것은, URL이 달라지기 때문에 기존 캐시에 접근할 수 없다.

  • 서버 부하 가중

    뚱뚱한 URL에 해당하는 HTML 페이지를 다시 그려야 한다.

  • 이탈

    사용자가 특정 URL을 요청해서 뚱뚱한 URL 세션에서 이탈할 수 있다. 이탈하면, 그동안 쌓였던 데이터(장바구니 등)가 초기화된다.

  • 세션 간 지속성의 부재

    뚱뚱한 URL을 북마크하지않는 이상, 로그아웃 하면 모든 정보를 잃는다.

11.6 쿠키

쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용하는 방식이다.

11.6.1 쿠키의 타입

세션 쿠키(session cookie)와 지속 쿠키(persistent cookie) 두 가지 타입으로 나뉜다.

  • 세션 쿠키
    • 사용자가 사이트를 탐색할 때, 관련한 설정과 선호 사항들을 저장하는 임시쿠키
    • 브라우저를 닫으면 삭제됨
  • 지속 쿠키
    • 삭제되지 않고 더 길게 유지
    • 디스크에 저장되어, 브라우저를 닫거나 컴퓨터를 재시작해도 남아있음
    • 주기적으로 방문하는 사이트 정보나 로그인 이름을 유지

둘의 다른 점은 파기되는 시점뿐이다. 파기되는 시점을 가리키는 Expires 혹은 Max-Age 파라미터가 없으면 세션쿠키다.

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

  • (A) 처음 사용자가 웹 사이트에 방문하면 웹 서버는 사용자에 대해 아무것도 모른다.

  • (B) 웹 서버는 사용자가 다시 왔을 때, 해당 사용자를 식별하기 위한 유일한 값을 쿠키에 할당한다.

    그 리스트는 Set-cookie 또는 Set-cookie2 같은 HTTP 응답 헤더에 전달한다.

  • 브라우저는 서버에게 받은 Set-cookie 헤더에 있는 쿠키 콘텐츠를 브라우저 쿠키 데이터베이스에 저장한다.

  • (C) 사용자가 다시 같은 사이트를 방문하면, 브라우저는 서버가 이 사용자에게 할당했던

    쿠키를 Cookie 요청 헤더에 기술해 전송한다.

쿠키는 단순히 ID 번호만 넘기는 것은 아니며, 다른 정보들도 쿠키에 유지할 수 있다.

Cookie: name="rowanlee92"; phone="1234-777"

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

브라우저는 쿠키 정보를 저장할 책임이 있다. 이 시스템을 클라이언트 측 상태 라고 한다. 쿠키명세의 공식적인 이름은 HTTP 상태 관리 체계(HTTP State Management Mechanism)이다.

구글 크롬 쿠키

Mac의 경우 ~/Library/Application Support/Google/Chrome/Default/Cookies 파일이 구글 크롬 쿠키 SQLite 파일이다.

각 주요 필드의 의미는 다음과 같다.

creation_utc

쿠키가 생성된 시점을 초 단위로 기술

host_key

쿠키의 도메인

name

쿠키의 이름

value 쿠키의 값

path

쿠키와 관련된 도메인에 있는 경로

expires_utc

쿠키의 파기 시점을 초 단위로 기술

is_secure

이 쿠키를 SSL 커넥션일 경우에만 보낼지 여부

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

브라우저는 수백 수천 개의 쿠키를 가질 수 있지만, 쿠키 전부를 모든 사이트에 보내지 않는다.
보통 각 사이트에 2~3개의 쿠키만을 보낸다.

이유는 다음과 같다.

  • 쿠키를 모두 전달하면 성능이 크게 저하. 모두 전달하면 브라우저는 실제 콘텐츠의 바이트보다

    더 많은 쿠키 바이트를 전달하게 된다.

  • 쿠키 대부분 서버에 특화된 name/value 쌍을 포함하기 때문에, 대부분의 사이트에서는 무의미한 값이다.

  • 특정 사이트에서 제공한 정보를 신뢰하지 않는 사이트에서 가져갈 수 있어서 보안에 문제를 일으킬 수 있다.

브라우저는 쿠키를 생성한 서버에게만 쿠키에 담긴 정보를 전달한다.

google.com 에서 생성된 쿠키는 google 에만 보내고 naver.com에서 생성된 쿠키는 naver 에만 보낸다.

쿠키 Domain 속성

서버는 쿠키를 생성할 때 Set-cookie 응답 헤더에 Domain 속성을 기술해서 어떤 사이트가 해당 쿠키를 읽을 수 있는지 제어할 수 있다.

Set-cookie: user="rowanlee92"; domain="github.com"

예를 들어 사용자가 www.github.com, www.test.github.com 처럼 .github.com으로 끝나는 사이트를 방문하면 Cookie 헤더가 항상 적용된다.

Cookie: user="rowanlee92"

쿠키 Path 속성

URL 경로의 앞부분을 가리키는 Path 속성을 기술해서 해당 경로에 속하는 페이지에만 쿠키를 전달할 수 있다.

Set-cookie: pref=compact; domain="github.com"; path=/pro/

www.github.com으로 접근하면

Cookie: user="rowanlee92"

쿠키 한 개를 얻을 수 있고

www.github.com/pro/로 접근하면

Cookie: user="rowanlee92"
Cookie: pref=compact

두 가지 쿠키를 얻는다.

따라서, 쿠키는 일종의 상태정보 라고 할 수 있다.

11.6.5 쿠키 구성요소

쿠키 명세에는 Version 0 쿠키(넷스케이프 쿠키), Version 1 쿠키(RFC 2965)가 있다.

Version 1은 RFC 6265 "HTTP State Management Mechanism"에 의해 폐기됨

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

최초의 쿠키는 넷스케이프가 정의함.

Set-Cookie: name=value [; expires=date] [; path=path] [; domain=domain] [; secure]

Cookie: name1=value1 [; name2=value2] ...

Set-Cookie 헤더

Set-Cookie 헤더는 name=value 이름과 값을 가져야 한다. 쿠키 옵션 속성들은 세미콜론으로 이어서 기술한다.

아래의 표는 Set-Cookie 필드 정보이다.

Set-Cookie 속성설명 및 용례
name=value(필수) 큰 따옴표로 감싸지 않고 세미콜론, 쉼표, 등호, 공백을 포함하지 않는 문자열
Expires(선택) 쿠키의 생명주기를 가리키는 날짜 문자열. 사용할 수 있는 타임존은 GMT. Expires가 없다면 세션쿠키
Domain(선택) 이 속성에 기술된 도메인을 사용하는 서버로만 쿠키를 전송. 도메인 명시되어있지 않으면, Set-Cookie 응답을 생성한 서버의 호스트 명이 기본값으로 사용됨
Path(선택) 서버에 있는 특정 경로만 쿠키를 할당. 경로가 명시되어있지 않으면, Set-Cookie 응답을 전달하는 URL의 경로가 사용됨
Secure(선택) 이 속성이 포함되면, 쿠키는 HTTP가 SSL 보안 연결 사용할 때만 전달

Cookie 헤더

클라이언트가 서버에 요청 보낼 때는, Domain, Path, Secure 필터들이 현재 요청하려는 사이트에 적합하면 파기되지 않은 쿠키들을 함께 보낸다. 모든 쿠키는 Cookie 헤더에 이어 붙여 보낸다.

Cookie: session-id=002-123341-4444444; session-id-time=1007884800

11.6.7 Version 1 (RFC 2965) 쿠키

현재 폐기된 쿠키라 정리하지 않음. 필요 시 HTTP 완벽가이드 p.312~315 참조

11.6.8 쿠키와 세션 추적

사용자가 Amazon.com에 방문하면 일어나는 트랜젝션의 연속을 설명한다. 이때 세션쿠키가 사용된다.

  • 브라우저가 Amazon.com 루트 페이지를 요청
  • 서버는 클라이언트를 전자상거래 소프트웨어 URL로 리다이렉트
  • 클라이언트는 리다이렉트 URL로 요청
  • 서버는 응답에 두 개의 세션 쿠키를 기술 후, 사용자를 다른 URL로 리다이렉트.
  • 클라이언트는 앞에 받은 두 개의 쿠키와 함께 새로운 URL로 요청
  • 서버는 home.html 페이지로 리다이렉트 시키고 쿠키 두 개를 추가적으로 첨부
  • 클라이언트는 home.html 페이지를 요청하고 총 4개의 쿠키를 전달
  • 서버는 콘텐츠를 보낸다.

11.6.9 쿠키와 캐싱

쿠키 트랜젝션과 관련된 문서를 캐싱하는 것은 주의해야한다. 이전 사용자의 쿠키가 다른 사용자에게 할당돼거나, 누군가의 개인 정보가 다른 사람에게 노출될 수 있기 때문이다.

캐시되지 말아야 할 문서가 있다면 표시하라

문서가 Set-Cookie 헤더를 제외하고 캐시를 해도 될 경우라면 문서에 명시적으로 Cache-Control: no-cache="Set-Cookie"를 기술한다. 또한, 캐시를 해도 되는 문서에 Cache-Control: public을 사용

Set-Cookie 헤더를 캐시 하는 것에 유의하라

캐시가 모든 요청마다 원 서버와 재검사시켜 클라이언트로 가는 응답에 Set-Cookie 헤더 값을 기술할 수 있도록 원 서버는 다음의 헤더를 캐시 문서에 추가한다.

Cache-Control: must-revalidate, max-age=0

Cookie 헤더를 가지고 있는 요청을 주의하라

Cookie 헤더가 오면, 결과 콘텐츠가 개인정보를 담고 있을 수도 있다는 힌트다. 개인 정보는 캐시되지 않도록 표시되어야 하지만, 그 표시를 하지 않는 서버도 있다.

Set-Cookie가 있는 이미지에 대해서는 캐시를 하지만, 텍스트는 캐시를 하지 않는 캐시도 있다. 따라서, 캐시 이미지에 파기 시간이 0인 Cookie 헤더를 설정해서 매번 재검사를 하도록 강제한다.

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

개인정보 정책에만 유의한다면, 쿠키에 관련한 위험성보다 세션 조작이나 트랜젝션상의 편리함이 더 크다.

References

profile
얍얍 개발 펀치

0개의 댓글