11. 클라이언트 식별과 쿠키
- 웹 서버는 서로 다른 수천 개의 클라이언트들과 동시에 통신합니다.
- 때로는 모든 요청을 처리하는 것 뿐만 아니라 서버와 통신하고 있는 클라이언트를 추적해야 할 수도 있습니다.
- 아래에서는 서버가 통신하는 대상을 식별하는 데 사용하는 기술입니다.
#
11.1 개별 접촉- HTTP는 익명으로 사용하며 상태가 없으며 요청과 응답으로 통신하는 프로토콜입니다.
- 웹 사이트는 요청을 보낸 사용자를 식별하거나 방문자가 보낸 연속적인 요청을 추적하기 위해 약간의 정보를 이용할 수 있습니다.
- 개별 인사, (사용자에게 특화된 환영 메시지나 페이지 내용을 만듭니다.)
- 사용자 맞춤 추천, 온라인 상점은 고객이 좋아할 것이라 예상되는 제품들을 추천합니다.
- 저장된 사용자 정보, 복잡한 주소와 신용카드 정보를 데이터베이스에 저장함으로 편리함을 제공합니다.
- 세션 추적, HTTP 트랜잭션은 상태가 없습니다. 그렇기 때문에 사용자의 상태를 남기기 위해 사용자에게서 오는 HTTP 트랜잭션을 식별할 방법이 필요합니다.
아래에서는 사용자를 식별하는 기술입니다. (각기 장단점이 있습니다.)
- 사용자 식별 관련 정보를 전달하는 HTTP 헤더들
- 클라이언트 IP 주소 추적으로 알아낸 IP 주소로 사용자를 식별
- 사용자 로그인 인증을 통한 사용자 식별
- URL에 식별자를 포함하는 기술인 뚱뚱한 URL
- 식별 정보를 지속해서 유지하는 강력하고 효율적인 쿠키
#
11.2 HTTP 헤더사용자에 대한 정보를 전달하는 HTTP 헤더
헤더 이름 | 헤더 타입 | 설명 |
---|---|---|
From | 요청 | 사용자의 이메일 주소 |
User-Agent | 요청 | 사용자의 브라우저 |
Referer | 요청 | 사용자가 현재 링크를 타고 온 근원 페이지 |
Authorization | 요청 | 사용자 이름과 비밀번호 |
Client-ip | 확장(요청) | 클라이언트의 IP 주소 |
X-Forwarded-For | 확장(요청) | 클라이언트의 IP 주소 |
Cookie | 확장(요청) | 서버가 생성한 ID 라벨 |
#
11.3 클라이언트 IP 주소초기에는 웹에서는 사용자 식별에 클라이언트의 IP 주소를 사용했습니다. 그러나 아래의 약점을 가집니다.
- 클라이언트 IP 주소는 사용자가 아닌 사용하는 컴퓨터를 의미합니다.
- 많은 인터넷 서비스 제공자(ISP)는 사용자가 로그인하면 동적으로 IP 주소를 할당합니다.
- 보안을 강화하고 부족한 주소들을 관리하려고 많은 사용자가 네트워크 주소 변화 방화벽을 통해 인터넷을 사용합니다.
- 보통 HTTP 프락시와 게이트웨이는 원 서버에 새로운 TCP 연결을 합니다.
현재도 세션 간에 사용자를 추적하려고 클라이언트 IP 주소를 사용하는 웹사이트가 있으나 이 방식은 제대로 동작하지 않기 때문에 사용하지 않습니다.
#
11.4 사용자 로그인- IP 주소로 사용자를 식별하려는 수동적인 방식보다, 웹 서버는 사용자 이름과 비밀번호로 인증할 것을 요구해서 사용자에게 명시적으로 식별 요청을 할 수 있습니다.
- 웹 사이트 로그인이 더 쉽도록 HTTP는 WWW-Authenticate와 Authorization 헤더를 사용해 웹 사이트에 사용자 이름을 전달하는 자체적인 체계를 가지고 있습니다.
- 서버에서 사용자가 사이트에 접근하기 전에 로그인을 시키고자 한다면 HTTP 401 Login Required 응답 코드를 브라우저에 보낼 수 있습니다.
#
11.5 뚱뚱한 URL- 어떤 웹 사이트는 사용자의 URL마다 버전을 기술하여 사용자를 식별하고 추적하였습니다.
- 사용자의 상태 정보를 포함하고 있는 URL을 뚱뚱한 URL이라고 합니다.
- 웹 서버와 통신하는 독립적인 HTTP 트랜잭션을 하나의 세션 혹은 방문으로 묶는 용도로 뚱뚱한 URL을 사용할 수 있습니다.
- 뚱뚱한 URL은 사이트를 브라우징하는 사용자를 식별하는데 사용할 수 있습니다.
하지만 아래의 문제가 있습니다.
- 못생긴 URL
- 브라우저에 보이는 뚱뚱한 URL은 새로운 사용자들에게 혼란을 줍니다.
- 공유하지 못하는 URL
- 뚱뚱한 URL은 특정 사용자와 세션에 대한 상태 정보를 포함하며 공유하기 어렵습니다.
- 캐시를 사용할 수 없음
- URL로 만드는 것은, URL이 달라지기 때문에 기존 캐시에 접근할 수 없다는 것을 의미합니다.
- 서버 부하 가중
- 서버는 뚱뚱한 URL에 해당하는 HTML 페이지를 다시 그려야합니다.
- 이탈
- 사용자가 링크를 타고 다른 사이트로 이동하는 경우, 뚱뚱한 URL 세션에서 이탈하기가 쉽습니다.
- 세션 간 지속간의 부재
- 사용자가 특정 뚱뚱한 URL을 북마킹하지 않는 이상, 로그아웃시 모든 정보를 잃습니다.
#
11.6 쿠키- 쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용하는 방식입니다.
- 쿠키는 위의 문제점들이 없지만, 쿠키만으로 어려운 경우는 앞의 기술들을 함께 사용하기도 합니다.
- 쿠키는 캐시와 충돌할 수 있으므로 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을 캐싱하지 않습니다.
#
쿠키의 타입크게 세션 쿠키(session cookie)와 지속 쿠키(persistent cookie) 두 가지 타입으로 나눠집니다.
- 세션 쿠키는 사용자가 사이트를 탐색할 때, 관련한 설정과 선호 사항들을 저장하는 임시 쿠키입니다.
- 세션 쿠키는 사용자가 브라우저를 닫으면 삭제됩니다.
- 지속 쿠키는 삭제되지 않고 더 길게 유지됩니다.
- 지속 쿠키는 디스크에 저장되어 브라우저를 닫거나 컴퓨터를 재시작하더라도 남아있습니다.
- 지속 쿠키는 사용자가 주기적으로 방문하는 사이트에 대한 설정 정보나 로그인 이름을 유지하려고 사용합니다.
세션 쿠키와 지속 쿠키의 다른 점은 파기되는 시점뿐입니다.
#
쿠키는 어떻게 동작하는가- 쿠키는
임의의 이름=값
형태의 리스트를 가지고 리스트는 Set-Cookie, Set-Cookie2 같은 HTTP 응답 헤더에 기술되어 사용자에게 전달합니다. - 쿠키는 어떤 정보든 포함할 수 있지만 서버가 사용자 추적 용도로 생성한 유일한 단순 식별 번호만 포함하기도 합니다.
#
쿠키의 상자 : 클라이언트 측 상태쿠키의 기본적인 발상은 브라우저가 서버 관련 정보를 저장하고, 사용자가 해당 서버에 접근할 때마다 그 정보를 함께 전송하게 하는 것입니다.
- 브라우저는 쿠키 정보를 저장할 책임이 있는데, 이 시스템을 클라이언트 측 상태라고 합니다.
#
구글 크롬 쿠키- creation_utc : 쿠키가 생성된 시점
- host_key : 쿠키의 도메인
- name : 쿠키의 이름
- value : 쿠키의 값
- path : 쿠키와 관련된 도메인에 있는 경로
- expire_utc : 쿠키의 파기 시점
- secure : 쿠키를 SSL 커넥션일 경우에만 보낼지를 가리킵니다.
#
마이크로소프트 인터넷 익스플로러 쿠키- 캐시 디렉터리에 각각의 개별 파일로 쿠키를 저장합니다.
- 파일에 있는 각 쿠키의 첫번째 줄은 쿠키이름이고 다음 줄은 쿠키의 값입니다.
- 세 번째 줄에는 도메인과 경로가 있습니다.
#
사이트마다 각기 다른 쿠키들브라우저는 수백 수천 개의 쿠키를 가지고 있을 수 있지만 쿠키 전부를 모든 사이트에 보내지 않습니다. 일반적으로는 두 개 혹은 세 개의 쿠키만을 보냅니다.
- 쿠키를 모두 전달하면 성능이 크게 저하됩니다.
- 쿠키들 대부분은 서버에 특화된 이름/값 쌍을 포함하고 있기 때문에 대부분 사이트에서는 인식하지 않는 무의미한 값입니다.
- 모든 사이트에 쿠키 전체를 전달하는 것은 특정 사이트에서 제공한 정보를 신뢰하지 않는 사이트에서 가져갈 수도 있습니다.
보통 브라우저는 쿠키를 생성한 서버에게만 쿠키에 담긴 정보를 전달합니다.
#
쿠키의 Domain 속성- 서버는 쿠키를 생성할 때 Set-Cookie 응답 헤더에 Domain 속성을 기술해서 어떤 사이트가 그 쿠키를 읽을 수 있는지 제어할 수 있습니다.
#
쿠키의 Path 속성- 웹 사이트 일부에만 쿠키를 적용할 수 있습니다.
- URL 경로의 앞부분을 가리키는 Path 속성을 기술해서 해당 경로에 속하는 페이지에만 쿠키를 전달합니다.
#
쿠키 구성요소- 현재 사용되는 쿠키 명세에는 Version 0 쿠키(넷스케이프 쿠키)와 Version 1 쿠키(RFC 2965)가 있습니다.
- Version 1 쿠키는 Version 0 쿠키의 확장으로 널리 쓰이지는 않습니다.
#
Version 0(넷스케이프) 쿠키아래의 형태를 가지고 있습니다.
Version 0 Set-Cookie 헤더
Set-Cookie 속성 | 설명과 용례 |
---|---|
이름=값 | 필수 속성, 이름과 값의 조합 |
Expires | 선택 속성, 쿠키의 생명주기 |
Domain | 선택 속성, 브라우저는 이 속성에 기술된 도메인을 사용하는 서버 호스트 명 |
Path | 선택 속성, 특정 문서에만 쿠키를 할당 가능 |
Secure | 선택 속성, 쿠키는 HTTP가 SSL 보안 연결시만 쿠키 전송 |
Version 0 Cookie 헤더
쿠키는 Cookie 헤더에 한데 이어 붙여 보냅니다.
#
Version 1 (RFC 2965) 쿠키- 넷크페이프 표준보다 좀 더 복잡하며 모든 브라우저나 서버에서 지원하지 않습니다.
- 이전 쿠키와의 변경사항은 다음과 같습니다.
- 쿠키마다 그 목적을 설명하는 설명문
- 파기 주기에 상관없이 브라우저가 닫히면 쿠키를 강제로 삭제
- 절대 날짜 값 대신에 초 단위의 상대 값으로 쿠키의 생명주기를 결정할 수 있는 Max-Age
- 단순히 도메인과 경로뿐 아니라 URL의 포트번호로도 쿠키를 제어할 수 있습니다.
- 도메인, 포트, 경로 필터가 있으면 Cookie 헤더에 담겨 되돌려 보냅니다.
- 호환되는 버전번호
- 사용자 이름과 추가적인 키워드를 구별하기 위해 Cookie 헤더에 $ 접두어가 있습니다.
Set-Cookie2속성 | 설명 및 용례 |
---|---|
이름=값 | 필수 속성, 이름과 값의 조합 |
Version | 필수 속성, 쿠키 명세 버전 |
Comment | 선택 속성, 서버가 쿠키를 사용하려는 의도 |
CommentURL | 선택 속성, 쿠키 목적과 정책에 대한 상세 웹페이지 |
Discard | 선택 속성, 클라이언트가 프로그램 종료시 해당 쿠키 삭제 |
Domain | 선택 속성, 위와 동일 |
Max-Age | 선택 속성, 쿠키의 생명주기를 초 단위로 산정한 정수 값 |
Path | 선택 속성, 위와 동일 |
Port | 선택 속성, 포트에 해당하는 서버만 쿠키 전달 |
Secure | 선택 속성, 위와 동일 |
Version 1 Cookie 헤더
다음과 같이 받은 경우.
클라이언트는 요청시 다음의 헤더를 보내게 됩니다.
#
쿠키와 세션 추적- 쿠키는 웹 사이트에 수차례 트랜잭션을 만들어내는 사용자를 추적하는데 사용합니다.
#
쿠키와 캐싱- 쿠키 트랜잭션과 관련된 문서를 캐싱하는 것은 주의해야 합니다.
#
캐시가 되지 말아야 할 문서가 있으면 표시하라- 문서를 캐시하면 될지 안될지는 문서의 소유자가 제일 압니다.
- 이 경우,
Cache-Control: no-cache="Set-Cookie"
을 기술해서 명확히 표시해야합니다.
#
Set-Cookie 헤더를 캐시 하는 것에 유의하라- 만약 응답이 Set-Cookie 헤더를 가지고 있으면, 본문은 캐싷라 수 있지만 Set-Cookie 헤더를 캐시하는 것은 주의를 기울여야만 합니다.
- 어떤 캐시는 응답을 저장하기 전에 Set-Cookie 헤더를 제거하는 경우도 있습니다.
- 캐시가 모든 요청마다 원 서버와 재검사시켜 클라이언트로 가는 응답에 Set-Cookie 헤더 값을 기술해서 이 문제를 개선할 수 있습니다.
#
Cookie 헤더를 가지고 있는 요청을 주의하라- 요청이 Cookie 헤더와 함께 오면, 결과 콘텐츠가 개인저보를 담고 있을 수도 있습니다.
- 경우에 따라 Cookie를 캐싱하거나 혹은 캐싱하지 않는 경우도 많습니다.
#
쿠키, 보안 그리고 개인정보- 쿠키를 사용하지 않도록 비활성화시킬 수도 있고, 로그 분석과 같은 다른 방법으로 대체가능하므로 그 자체가 보안상으로 엄청나게 위험한 것은 아닙니다.
- 개인정보를 다루거나 사용자를 추적하는 기술은 잘못된 의도로 사용될 수 있기 때문에 항상 조심하는 것이 좋습니다.
- 사이트의 개인정보 정책에만 유의한다면, 쿠키에 관련한 위험성보다 세션 조작이나 트랜잭션 상의 편리함이 더 큽니다.