10장. HTTP2.0 / 12장. 기본 인증 환일님 블로그
13장. 다이제스트 인증 준수님 노션
웹 서버는 동시에 서로 다른 수천 개의 클라이언트들과 통신한다. 따라서 서버들은 클라이언트로부터 받은 요청을 처리하는 것 뿐만 아니라, 클라이언트를 추적할 수도 있어야 한다. 이 장에서는 서버가 통신 대상을 식별하는데에 사용하는 기술을 알아본다.
HTTP 트랜잭션은 상태가 없고(stateless), 각 요청과 응답이 독립적으로 일어난다. 따라서 많은 웹사이트에서 사용자가 사이트와 상호작용할 수 있도록 사용자의 상태를 남긴다. 이렇게 상태를 유지하기 위해서는 HTTP 트랜잭션을 식별할 방법이 필요하다. 이 장에서 알아볼 내용은 다음과 같다.
사용자에 대한 정보를 제공하는 가장 일반적인 HTTP 요청 헤더는 아래와 같다.
From 헤더는 이메일 주소를 담지만 악의적으로 메일 주소를 모아서 스팸 메일을 보낼 수 있기 때문에 최근에는 브라우저에서 From 헤더로 이메일 주소를 보내지 않는다.
User-Agent 는 특정 브라우저에서 제대로 동작하도록 속성에 맞춰 콘텐츠를 최적화하는 데 유용할 수 있으나, 사용자를 식별하는 데에는 무리가 있다.
Referer 헤더를 통해서는 사용자의 웹 사용 행태나 취향 등을 파악할 수 있다.
초기 웹 개발자들은 사용자 식별에 클라이언트 IP 주소를 사용하려고 했다. 하지만 다음과 같은 단점이 있었다.
IP 주소로 사용자를 식별하려는 수동적인 방법보다는 인증 요구를 통해 식별 요청을 할 수 있다. HTTP 는 WWW-Authenticate 와 Authentication 헤더를 사용해 사용자 정보를 전달하는 자체적인 체계를 가지고 있다.
로그인 후에는 사용자 식별정보 토큰을 Authorization 헤더에 담아 한 세션이 진행되는 동안 식별을 유지한다.
사용자에게 할당된 식별번호를 URL 경로의 처음이나 끝에 추가하여 확장한다. 사이트 내부를 돌아다니면, 서버가 URL 에 있는 상태 정보를 유지하는 하이퍼링크를 동적으로 생성한다.
...
<a href="/exec/obidos/tg/browse/-/229220/ref=gr_gifts/002-1145265-8016838">All Gifts</a><br>
<a href="/exec/obidos/wishlist/ref=gr_pl1_/002-1145265-8016838">Wish List</a><br>
...
<a href="http://s1.amazon.com/exec/varzea/tg/armed-forces/-//ref=gr_af_/002-1145265-8016838">Salute Our Troops</a><br>
<a href="/exec/obidos/tg/browse/-/749188/ref=gr_p4_/002-1145265-8016838">Free Shipping</a><br>
<a href="/exec/obidos/tg/browse/-/468532/ref=gr_returns/002-1145265-8016838">Easy Returns</a>
...
위의 예제는 Amazon 에서 뚱뚱한 URL을 사용하는 경우이다. URL 끝에 사용자 식별 정보인 002-1145265-8016838
가 계속해서 따라 다니는 것을 볼 수 있다.
사용자가 처음 방문하면 고유 ID가 생성되고, 그 값을 서버가 변환하여 URL 에 추가하는 동시에 사용자를 뚱뚱한 URL 로 리다이렉트 시킨다. 서버가 뚱뚱한 URL 요청을 받으면, 사용자와 관련된 정보를 찾아서 모든 하이퍼링크를 뚱뚱한 URL로 바꾼다. 이러한 방식으로 사용자를 식별할 수 있지만 이 기술에도 문제점이 있다.
쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용되는 방식이다. 넷스케이프가 최초로 개발하였으며, 지금은 모든 브라우저에서 지원한다.
쿠키는 캐시와 충돌할 수 있어서, 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을 캐싱하지 않는다.
쿠키는 크게 세션 쿠키(session cookie)와 지속 쿠키(consistent cookie) 두 가지 타입으로 나뉜다.
세션 쿠키와 지속 쿠키의 차이점은 파기 시점이다. Discard 파라미터가 설정되어 있거나, Expires 혹은 Max-Age 파라미터가 없으면 세션 쿠키가 된다.
쿠키는 서버가 사용자에게 "안녕, 내 이름은 ~" 라고 적어서 붙이는 스티커와 같다. 사용자가 웹 사이트에 방문하면, 웹 사이트는 서버가 사용자에게 붙인 스티커를 읽을 수 있다.
사용자가 처음 웹 사이트에 접속했을 때, 서버는 사용자에 대해 아무것도 알지 못한다. 해당 사용자가 다시 돌아왔을 때, 식별하기 위한 목적으로 유일한 식별값을 쿠키에 할당한다. HTTP 응답 헤더에 Set-Cookie 혹은 Set-Cookie2(확장 헤더)에 기술되어 전달한다.
쿠키에는 어떠한 정보도 포함될 수 있지만, 사용자 추적 용도로 생성한 단순 식별 번호만 포함하기도 한다. 많은 웹 서버가 아래와 같이 여러 정보를 쿠키에 포함시키려고 한다.
Cookie: name="David"; phone="555-1212"
브라우저는 서버로부터 헤더에 담겨온 쿠키 콘텐츠를 브라우저 쿠키 데이터베이스에 저장한다. 사용자가 같은 사이트를 방문하면, 서버가 할당한 해당 쿠키를 Cookie 요청 헤더에 기술하여 전송한다.
쿠키의 사용 방법은 브라우저가 서버 관련 정보를 저장하고, 사용자가 해당 서버에 접근할 때마다 그 정보를 함께 전송하는 것이다. 따라서 브라우저는 쿠키 정보를 저장할 책임이 있고, 이를 클라이언트 측 상태
라고 한다. 쿠키 명세에서는 HTTP 상태 관리 체계(HTTP State Management Mechanism)
이라고 지칭한다.
각 브라우저는 각기 다른 방식으로 쿠키를 저장한다. 구글 크롬은 SQLite 파일에 쿠키를 저장한다. 각 PC의 브라우저마다 이를 직접 확인할 수 있다.
경로 : Users/pc이름/Library/Application Support/Google/Chrome/Default
$ sqlite3 Cookies
$ .headers on
$ .mode column
$ .tables(table 확인)
$ select * from cookies
브라우저는 사이트마다 다른 쿠키를 받아서 저장하지만, 해당 사이트에 접속할 때 가지고 있는 모든 쿠키를 전송하지 않는다. 쿠키를 생성한 서버에만 해당 쿠키에 담긴 정보를 제공한다.
많은 웹 사이트가 온라인 광고를 관리하는 업체들과 계약을 맺는다. 온라인 광고는 마치 웹 사이트의 일부처럼 제작되고, 지속 쿠키를 만든다. 같은 광고사와 계약을 맺은 서로 다른 사이트를 사용자가 방문하면, 이미 앞서 만든 지속 쿠키를 광고사 서버로 전송한다. 그 이유는 지속 쿠키의 도메인이 같기 때문이다. 그리고 광고사는 이러한 기술에 Referer 헤더를 접목하여 사용자의 프로필과 웹 사이트 방문 정보에 대한 방대한 데이터를 구축할 수 있다.
그러나 최신 브라우저는 개인정보 설정 기능을 통해 이러한 광고사의 쿠키 사용 방식에 제약을 가하도록 하고 있다.
쿠키 Domain 속성
서버는 쿠키를 생성할 때, Set-Cookie 응답 헤더에 Domain 속성을 기술하여 어떤 사이트가 해당 쿠키를 읽을 수 있는지를 파악할 수 있다.
Set-Cookie: user="mary17"; domain="airtravel.com"
위와 같은 경우, .airtravel.com
도메인을 가진 모든 사이트에 해당 쿠키를 전달한다는 뜻이다. 따라서 www.airtravel.com
나 special.airtravel.com
같이 .airtravel.com
로 끝나는 사이트를 방문하면 브라우저는 해당 쿠키를 서버에 전송한다.
Cookie: user="mary17"
쿠키 Path 속성
웹 사이트 내에서 일부에만 쿠키를 적용할 수도 있다. URL 경로의 앞부분을 가리키는 Path 속성을 기술하여, 해당 경로에 속하는 페이지에만 쿠키를 전달한다.
Set-Cookie: pref=compact; domain="airtravel.com"; path=/autos/
위와 같은 경우, 만약 사용자가 www.airtravel.com/specials.html
에 접근하면 다음의 쿠키만 얻게 된다.
Cookie: user="mary17"
그러나 www.airtravel.com/autos/suv/index.html
로 접근하게 되면 쿠키는 다음과 같다.
Cookie: user="mary17"
Cookie: pref="compact"
추가된 value 값을 얻을 수 있게 된다.
현재 사용되는 쿠키 명세에는 Version 0 쿠키(흔히 '넷스케이프 쿠키' 라고 불림)와 Version 1 쿠키('RFC 2956')가 있다. Version 1 쿠키는 Version 0 쿠키의 확장으로 많이 쓰이지는 않는다.
최초의 쿠키 명세는 넷스케이프가 정의했다.
Set-Cookie: name=value [; expires=date] [; path=path] [; domain=domain] [; secure]
Cookie: name1=value1 [; name2=value2] ....
Set-Cookie 헤더는 쿠키의 이름과 값을 가져야 한다. 다른 속성 필드들은 아래와 같다.
요일, DD-MM-YY HH:MM:SS GMT
이다. 타임존은 GMT 만 사용할 수 있다. 날짜 요소 사이에는 반드시 (-)로 연결되어야 한다. 쿠키에 Expires 가 명시되지 않으면 해당 쿠키는 사용자의 세션이 끝날 때 파기된다./foo
경로는 /foobar
와 /foo/bar.html
모두 해당된다. /
경로는 도메인 내의 모든 경로에 해당된다. 경로가 명시되지 않으면, Set-Cookie 응답을 전달하는 경로가 사용된다.클라이언트가 서버에 요청을 보낼 때는 Domain, Path, Secure 속성들이 현재 사이트와 일치하면서 아직 파기되지 않은 쿠키를 보낸다. 모든 쿠키는 Cookie 헤더에 이어 보낸다.
Cookie: session-id=002-112-2343824; session-id-time=1007884800
RFC2965는 폐기되어 더 이상 지원되지 않음.
자세한 내용은 책 312p ~ 316p 참조
쿠키의 목적은 사용자를 추적하는 것이고, 전자상거래 웹 사이트의 경우에는 사용자의 장바구니를 유지하기 위해 세션 쿠키를 사용한다.
미국 아마존에서의 트랜잭션을 예로 들면 아래와 같다.
쿠키는 캐싱에 주의해야 한다. 다른 사용자의 쿠키가 할당되거나 개인정보가 타인에게 노출될 수 있기 때문이다.
Cache-Control: no-cache="Set-Cookie"
Cache-Control: must-revalidate, max-age=0
쿠키와 IP주소, Referer 헤더 등을 활용하면 사용자의 프로필과 사용 패턴에 대해 데이터를 수집할 수 있다. 쿠키에 대한 부정적인 여론이 많지만, 제공하는 정보를 누가 받는지 명확히 알고 개인정보 정책에만 유의하면 위험성보다는 편리함이 더 큰 기술이다.
1998년 미 재무성 컴퓨터 사고 자문단의 위험성 평가서 내용은 아래와 같다.
쿠키는 사용자의 웹 사이트 방문 이력이나 전달 받은 사용자 고유 식별값을 서버에 다시 보내주는 용도일 뿐이다. 대부분의 쿠키는 브라우저를 빠져나감과 동시에 제거되며, 지속 쿠키는 파기 시간 전까지만 디스크에 남는다. 쿠키 말고도 웹 로그 파일을 통해서 사용자의 브라우징 습관을 추적할 수 있으며, 쿠키는 다만 이를 편리하게 해줄 뿐이다.