Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3부 11장] 클라이언트 식별과 쿠키 #12

Open
vo0a opened this issue Sep 18, 2022 · 1 comment
Open

[3부 11장] 클라이언트 식별과 쿠키 #12

vo0a opened this issue Sep 18, 2022 · 1 comment

Comments

@vo0a
Copy link

vo0a commented Sep 18, 2022

서버들은 서버와 통신하고 있는 클라이언트를 추적해야 할 수도 있다. 이 장에서는 서버가 통신하는 대상을 식별하는 데 사용하는 기술을 알아본다.

11.1 개별 접촉

  • HTTP는 익명으로 상태가 없고, 요청과 응답으로 통신하는 프로토콜이다. → 무상태(stateless)
  • 현대의 웹 사이트들은 개인화된 서비스를 제공하고 싶어한다.
  • 사용자에 대해 더 많은 것을 알고 싶어 하고 사용자들이 브라우징하는 것을 기록하고 싶어한다.
  • 유명 온라인 쇼핑 사이트는 여러가지 방식으로 사이트를 개인화시켜서 사용자에게 제공한다.

개별 인사

  • 온라인 쇼핑이 개인에게 맞춰져 있는 것처럼 느끼게 하려고 사용자에게 특화된 메시지나 페이지 내용을 만든다.

사용자 맞춤 추천

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

저장된 사용자 정보

  • 고객의 복잡한 주소와 신용카드 정보를 데이터베이스 등에 저장하여 고객이 매번 입력하지 않도록 할 수 있다.
  • 온라인 쇼핑이 고객을 한번 식별하고 나면, 쇼핑을 더 편하게 하기 위해 그 정보를 사용할 수 있다.

세션 추적

  • HTTP 트랜잭션은 상태가 없기 때문에 각 요청 및 응답은 독립적으로 일어난다.
  • 많은 웹 사이트는 사용자가 사이트와 상호작용할 수 있게 사용자의 상태를 남긴다(eg. 장바구니)
  • 이렇게 상태를 유지하려면, 웹 사이트는 각 사용자에게서 오는 HTTP 트랜잭션을 식별할 방법이 필요하다.

이 장에서는 다음과 같은 사용자 식별 기술을 논의한다.

  • 사용자 식별 관련 정보를 전달하는 HTTP 헤더들
  • 클라이언트 IP 주소 추적으로 알아낸 IP 주소로 사용자를 식별
  • 사용자 로그인 인증을 통한 사용자 식별
  • URL에 식별자를 포함하는 기술인 뚱뚱한 URL
  • 식별 정보를 지속해서 유지하는 강력하면서도 효율적인 기술인 쿠키

11.2 HTTP 헤더

사용자에 대한 정보를 전달하는 가장 일반적인 일곱 가지 HTTP 요청 헤더.

From 헤더

  • 각 사용자의 이메일 주소로 사용자를 식별할 수 있지만, 악의적인 서버가 이메일을 모아서 스팸 메일을 발송하는 문제로 From 헤더를 보내는 브라우저는 많지 않다.

User-Agent 헤더

  • 사용자가 쓰고있는 브라우저의 이름과 버전 정보, 어떤 경우에는 운영체제에 대한 정보를 포함한다.
  • 이는 특정 브라우저에서 제대로 동작하도록 그것들의 속성에 맞춰 콘텐츠를 최적화 하는데 유용할 수 있지만 사용자를 식별하는 데는 큰 도움이 되지 않는다.

Referer

  • 사용자가 현재 페이지로 유입하게 한 웹페이지의 URL을 가리킨다.
  • Refere 헤더 자체만으로 사용자를 식별할 수 없지만 사용자가 전에 방문했던 페이지를 알 수 있다.
  • 사용자의 웹 사용 형태나 취향을 파악하는데 사용한다.

From, User-Agent, Refere 헤더는 사용자를 확실히 식별하기엔 정보가 부족하다.

11.3 클라이언트 IP 주소

  • 클라이언트의 IP 주소를 사용하는 방식은 사용자가 확실한 IP 주소를 갖고있고, IP는 좀처럼(혹은 절대) 바뀌지 않고, 웹 서버가 요청마다 클라이언트의 IP 주소를 알 수 있다면 문제없이 동작한다.

  • 클라이언트의 IP 주소는 보통 HTTP 헤더에 없지만 웹 서버는 HTTP 요청을 보내는 TCP 커넥션의 반대쪽 IP를 알아낼 수 있다.

    eg. status = getpeername(tcp_connection_socket...);

클라이언트 IP 주소로 사용자를 식별하는 방법의 약점

  1. 클라이언트 IP 주소는 사용자가 아닌 사용자 컴퓨터를 가리킨다. 여러명이 한 컴퓨터를 이용할 경우 각각의 사용자를 식별할 수 없다.
  2. 많은 ISP는 사용자가 로그인하면 동적으로 IP를 할당한다.
  3. 보안을 강화하고 부족한 주소들을 관리하려고 많은 사용자가 NAT 방화벽을 통해 인터넷을 사용한다. NAT 장비들은 클라이언트의 실제 IP 주소를 방화벽 뒤로 숨기고, 클라이언트의 실제 IP 주소를 내부에서 사용하는 방화벽 IP 주소로 변환한다.
  4. 보통, HTTP 프락시와 게이트웨이는 원 서버에 새로운 TCP를 연결한다. 웹 서버는 클라이언트의 IP 주소 대신 프락시의 IP 주소를 본다.일부 프락시는 클라이언트의 IP 주소를 보존하기 위해 Client-Ip나 X-Forward-For HTTP 같은 헤더를 사용하지만 모든 프락시가 이런식으로 동작하진 않는다.

11.4 사용자 로그인

  • 웹 서버는 사용자 이름과 비밀번호로 인증(로그인)할 것을 요구해서 사용자에게 명시적으로 식별 요청을 할 수 있다.
  • HTTP는 WWW-Authenticate와 Authorization 헤더를 사용해 웹 사이트에 사용자 이름을 전달하는 자체적인 체계를 가지고 있다.
  • 서버에서, 사용자가 사이트에 접근하기 전에 로그인을 시키고자 한다면 HTTP 401 Login Required 응답 코드를 브라우저에 보낼 수 있다. (브라우저는 사이트에 대한 로그인 정보를 가지고 있다가 요청을 보낼 때 같이 전달한다)
  • 브라우저는 로그인 대화상자를 보여주고, 다음 요청부터 Authorization 헤더에 기 정보를 기술하여 보낸다. (이 시점에 이름과 비밀번호를 포함한 Authorization 헤더를 추가, 이름과 비밀번호는 암호화하여 네트워크 상에서 제 3자가 보지 못하게 보호한다)

image

  • 하지만 사용자 로그인은 다양한 문제를 가지고 있다.
    • 사이트를 옮겨다닐 때마다 로그인
    • 사용자 이름 선점
    • 사용자 이름과 비밀번호의 길이와 조합 규칙이 다르다.

11.5 뚱뚱한 URL

  • 보통, URL은 URL 경로의 처음이나 끝에 어떤 상태 정보를 추가해 확장한다.
  • 사용자의 상태 정보를 포함하고 있는 URL을 뚱뚱한 URL이라고 한다.
  • Amazone.com에서 사용하는 뚱뚱한 URL의 예
    • <a href=/exec/obidos/tg/browse/-/229220/ref=gr_gifts/002-1145265-8016838>....html
    • 하이퍼링크에 002-1145265-8016838 같은 식별자를 붙인다
  • 각 URL은 웹 상점을 돌아다니는 사용자에게 할당된 식별번호(eg. 002-1145265-8016838)를 각 URL 뒤에 붙여서 사용자를 추적한다.
  • 웹 서버와 통신하는 독립적인 HTTP 트랜잭션을 하나의 '세션' 혹은 '방문'으로 묶는 용도로 뚱뚱한 URL을 사용할 수 있다.
  • 사용자가 웹 사이트에 처음 접속하면 유일한 ID가 생성되고, 그 값은 서버가 인식할 수 있는 방법으로 URL에 추가되며, 서버는 클라이언트를 이 뚱뚱한 URL로 리다이렉트 시킨다.

뚱뚱한 URL은 사이트를 브라우징하는 사용자를 식별할 수 있지만, 다음과 같은 문제가 있다.

못생긴 URL

  • 브라우저에 보이는 뚱뚱한 URL은 새로운 사용자들에게 혼란을 준다.

공유하지 못하는 URL

  • 뚱뚱한 URL은 특정 사용자와 세션에 대한 상태 정보를 포함한다.
  • 만약 그 주소를 누군가에게 메일이나 챗으로 보낸다면, 당신의 누적된 개인 정보를 본의 아니게 공유하게 되는 것이다.

캐시를 사용할 수 없음

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

서버 부하 가중

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

이탈

  • 사용자가 링크를 타고 다른 사이트로 이동하거나 특정 URL을 요청해서 의도치 않게 뚱뚱한 URL 세션에서 '이탈'하기 쉽다.
  • 사용자는 서비스를 사용하는 동안, 사전에 세션 정보가 추가된 링크를 사용해야 뚱뚱한 URL이 문제없이 동작할 수 있다.
  • 사용자가 이탈하게 되면, 지금까지의 진행사항(장바구니에 추가된 상품들 등)이 초기화 될 것이다.

세션 간 지속성의 부재

  • 사용자가 특정 뚱뚱한 URL을 북마킹하지 않는 이상, 로그아웃하면 모든 정보를 잃는다.

11.6 쿠키

  • 쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용하는 방식이다.
  • 쿠키는 앞서 설명한 기술들이 가지고 있던 문제점들은 없지만, 쿠키만으로 하기 힘든 일에는 앞서 설명한 기술들을 함께 사용하기도 한다.
  • 쿠키는 넷스케이프에서 최초로 개발했지만, 지금은 모든 브라우저에서 지원한다.
  • 쿠키는 캐시와 충돌할 수 있어서, 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을 캐싱하지 않는다.

1) 쿠키의 타입

  • 쿠키는 크게 세션 쿠키(session cookie)와 지속 쿠키(persistent cookie) 두 가지 타입으로 나눌 수 있다.
  • 세션 쿠키는 사용자가 사이트를 탐색할 때, 관련한 설정과 선호 사항들을 저장하는 임시 쿠키다.
    • 브라우저를 닫으면 삭제된다.
  • 지속 쿠키는 사용자가 주기적으로 방문하는 사이트에 대한 설정 정보나 로그인 이름을 유지하려고 사용한다.
    • 디스크에 저장되어, 브라우저를 닫거나 컴퓨터를 재시작해도 남아있다.
  • 쿠키는 Discard 파라미터가 설정되어 있거나, 파기되기까지 남은 시간을 가리키는 Expires 혹은 Max-Age 파라미터가 없으면 세션 쿠키가 된다.

2) 쿠키는 어떻게 동작하는가

  • 사용자가 웹 사이트에 방문하면, 웹 사이트는 서버가 사용자에게 붙인 모든 스티커를 읽을 수 있다.

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

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

  • 쿠키는 '임의의 이름=값' 형태의 리스트를 가지고, 그 리스트는 Set-Cookie 혹은 Set-Cookie2(확장 헤더) 같은 HTTP 응답 헤더에 기술되어 전달한다.

  • 쿠키는 어떤 정보든 포함할 수 있지만, 서버가 사용자 추적 용도로 생성한 유일한 단순 식별 번호만 포함하기도 한다.

  • 예를 들어 서버는 id="34294"라는 쿠키를 사용자에게 할당하는데, 서버는 이 쿠키 값으로 데이터베이스에서 사용자의 정보(구매 내용, 주소 정보 등)를 찾는데 사용할 수 있다.

  • 많은 웹 서버가 정보를 쿠키에 유지하려고 한다.

    eg. Cookie: name="Brian Totty" phone="555-1212"

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

  • 사용자가 미래에 같은 사이트를 방문하면, 브라우저는 서버가 이 사용자에게 할당했던 쿠키를 Cookie 요청 헤더에 기술해 전송한다.

image

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

  • 브라우저가 서버 관련 정보를 저장하고 그 서버에 접속할 때 마다 그 정보를 함께 보내는 것이다.
  • 브라우저는 쿠키 정보를 저장할 책임이 있는데, 이 시스템을 '클라이언트 측 상태'라고 한다.

구글 크롬 쿠키

  • 각 브라우저는 각기 다른 방식으로 쿠키를 저장한다.
  • 구글 크롬은 Cookies라는 SQLite 파일에 쿠키를 저장한다.
  • 각 행이 쿠키 한 개에 해당하며, 총 13개 필드가 있다.

image

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

  • 익스플로러는 캐시 디렉터리에 각각의 개별 파일로 쿠키를 저장한다.

4) 사이트마다 각기 다른 쿠키들

  • 브라우저는 수천 개의 쿠키를 가지고 있을 수 있지만, 각 사이트에 두 개 혹은 세 개의 쿠키를 보낸다. 이유는 다음과 같다.
    1. 쿠키를 모두 전달하면 브라우저는 실제 콘텐츠의 바이트 보다 더 많은 쿠키 바이트를 보내게 될 것이므로 성능이 크게 저하된다.
    2. 쿠키들의 대부분은 서버에 특화된 이름/값 쌍을 포함하고 있기 때문에, 대부분 사이트에서는 인식하지 않는 무의미한 값이다.
    3. 모든 사이트에 쿠키 전체를 전달하는 것은, 특정 사이트에서 제공한 쿠키를 신뢰하지 않는 사이트에서 가져갈 수 있어 보안 문제를 일으킬 것이다.

보통 브라우저는 쿠키를 생성한 서버에게만 쿠키에 담긴 정보를 전달한다. 많은 웹사이트는 광고를 관리하는 협력업체와 계약을 한다. 이 광고들은 웹 사이트 자체의 일부인 것처럼 제작되고, 지속 쿠키를 만들어낸다. 같은 광고사에서 제공하는 서로 다른 웹 사이트에 사용자가 방문하면, 지속 쿠키의 도메인이 같기 때문에 광고사 서버로 지속 쿠키가 전송된다.

이 기술에 Referer 헤더를 접목하여 방대한 사용자 데이터를 구축할 수 있다.

최신 브라우저들은 개인정보 설정 기능을 통해 협력업체의 쿠키 사용 방식에 제약을 가할 수 있도록 하고 있다.

Domain 속성

  • 서버는 쿠키를 생성할 때 Set-Cookie 응답 헤더에 Domain 속성을 기술하여 어떤 사이트가 그 쿠키를 읽을 수 있는지 제어할 수 있다.
  • 예를 들어 다음 HTTP 응답 헤더는 브라우저가 user="mary17"이라는 쿠키를 .airtravelbargains.com 도메인을 가지고 있는 모든 사이트에 전달한다는 의미다.user="mary17"; domain="airtravelbargains.com"
    • 만약 사용자가 www.airtravelbargains.com나 specials.airtravelbargains.com과 같이 .airtravelbargains.com로 끝나는 사이트를 방문하면 다음 Cookie 헤더가 항상 적용될 것이다.Cookie: user="mary17"

쿠키 Path 속성

  • URL 경로의 앞부분을 가리키는 Path 속성을 기술해서 해당 경로에 속하는 페이지만 쿠키를 전달한다.
  • www.airtravelbargains.com 사이트의 자동차를 대여하는 페이지인 www.airtravelbargains.com/autos/에서 사용자가 좋아하는 쿠키를 사용하려고 할 때 쿠키를 다음과 같이 생성한다.
    • Set-Cookie: pref=compact; domain="airtravelbargains.com"; path="/autos/"
  • 사용자가 www.airtravelbargains.com/specials.html에 접근하면 다음과 같은 쿠키만 얻게 된다.
    • Cookie: user="mary17"
  • 하지만 사용자가 www.airtravelbargains.com/autos/cheapo/index.html로 접근하면 다음과 같은 쿠키를 얻게 된다.
    • Cookie: user="mary17"
    • Cookie: pref=compact
  • 따라서 쿠키는 일종의 상태 정보라고 할 수 있으며, 서버가 생성하여 클라이언트에 전달하고, 클라이언트는 그 쿠키를 유효한 사이트에만 다시 전달하고 관리한다.

5) 쿠키 구성요소

  • 현재 사용되는 쿠키 명세에는 Version 0 쿠키(흔히 '넷스케이프 쿠키'라고 불린다)와 Version 1 쿠키(현재는 사용하지 않음)가 있다.

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

  • 최초의 쿠키 명세는 넷스케이프가 정의했다.
  • Version 0 쿠키는 Set-Cookie 응답 헤더와 Cookie 요청 헤데와 쿠키를 조작하는데 필요한 필드들을 정의하였다.
    • Set-Cookie: name=value [; expires=date][; path=path] [; domain=domain][; secure]
    • Cookie: name1=value1 [; name2=value2] ...

Version 0 Set-Cookie 헤더

  • Set-Cookie 헤더는 쿠키의 이름과 값을 가져야 한다.

  • 쿠키 옵션 속성들에 세미콜론으로 이어 기술한다.

    Set-Cookie 속성 설명과 용례
    이름=값 필수 속성.'이름'과 '값' 모두 큰 따옴표로 감싸지 않은 문자열.
    Set-Cookie: customer=Mary  
    Expires 선택적인 속성.쿠키의 생명주기를 가리키는 날짜 문자열.
    요일, DD-MM-YY HH:MM:SS GMT쿠키에 Expires를 명시하지 않으면 그 쿠키는 사용자의 세션이 끝날 때 파기될 것이다.  
    Set-Cookie: foo=bar; expires=Wednesday, 09-Nov-99 23:12:40 GMT  
    Domain 선택적인 속성.브라우저는 이 속성에 기술된 도메인을 사용하는 서버 호스트 명으로만 쿠키를 전송한다.도메인이 명시되어 있지 않으면 Set-Cookie 응답 헤더를 생성한 서버의 호스트 명을 기본값으로 사용한다.
    Set-Cookie: domain="joes-hardware.com"  
    Path 선택적인 속성.서버에 있는 특정 문서에만 쿠키를 할당 가능하다.만약 Path 속성에 기술된 값이 URL 경로 앞부분과 일치하면, 쿠키를 전달한다.예를 들면 '/foo' 경로는 '/foobar'와 '/foo/bar.html'에 들어맞는다.기본값으로는 Set-Cookie 응답을 전달하는 URL 경로가 사용된다.
    Set-Cookie: path=/orders  
    Secure 선택적인 속성.쿠키는 HTTP가 SSL 보안 연결을 사용할 때만 쿠키를 전송한다.
    Set-Cookie: private_id=519; secure  

Version 0 Cookie 헤더

  • 클라이언트가 서버에 요청을 보낼 때는, Domain, Path, Secure 필터들이 현재 요청 하려고 하는 사이트에 들어맞으면서 아직 파기되지 않은 쿠키들을 함께 보낸다.
  • 모든 쿠키는 Cookie 헤더 안에 한데 이어 붙여 보낸다.
    • Cookie: session-id=002-1145265-8016832; session-id-time=1007883800

7) Version 1 쿠키

  • 2011년에 폐기

8) 쿠키와 세션 추적

  • 쿠키는 웹 사이트에 수차례 트랜잭션을 만들어내는 사용자를 추적하는데 사용한다.
  • 전자상거래 웹 사이트는 사용자가 온라인 쇼핑을 하는 중에도 그들의 쇼핑카트를 유지하려 세션 쿠키를 사용한다.

amazon.com에 접속하면 일어나는 트랜잭션들의 연속

a : 브라우저가 amazon.com의 루트 페이지를 처음 요청한다.

b : 서버는 클라이언트를 전자상거래 소프트웨어 URL로 리다이렉트 시킨다.

c : 클라이언트는 리다이렉트 URL로 요청을 보낸다.

d : 서버는 응답에 두 개의 세션 쿠키를 기술하고 사용자를 다른 URL로 리다이렉트 시키며, 클라이언트는 다시 이 쿠키들을 첨부하여 요청을 보낸다. 새로은 URL은 자체적으로 어떤 상태 정보를 가지고 있으므로 뚱뚱한 URL이다.

e : 클라이언트는 새로운 URL을 요청을 앞서 받은 두 개의 쿠키와 함께 보낸다.

f : 서버는 home.html 페이지로 리다이렉트 시키고 쿠키 두 개를 더 첨부한다.

g : 클라이언트는 home.html 페이지를 가져오고 총 네 개의 쿠키를 전달한다.

h : 서버는 콘텐츠를 보낸다.

https://github.com/kimmin-ko/HTTP-The-Definitive-Guide/blob/master/images/amazonSessionCookie.png?raw=true

9) 쿠키와 캐싱

  • 쿠키 트랜잭션과 관련된 문서를 캐싱하는 것은 주의해야 한다.
  • 다음은 캐시를 다루는 기본 원칙에 대한 안내다.

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

  • 만약 문서가 Set-Cookie 헤더를 제외하고 캐시를 해도 될 경우라면 그 문서에 명시적으로 Cache-Control: no-cache="Set-Cookie"를 기술해서 명확히 표시한다.
  • 캐시를 해도 되는 문서에 Cache-Control: public을 사용하면 웹의 대역폭을 더 절약시켜준다.

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

  • 응답에 Set-Cookie 헤더를 가지고 있으면, 본문은 캐시할 수 있지만 Set-Cookie 헤더를 캐시하는 것은 주의가 필요하다.
  • 같은 Set-Cookie 헤더를 여러 사용자에게 보내면, 사용자 추적에 실패할 것이기 때문이다.
  • 일부 캐시는 응답을 저장하기 전에 Set-Cookie를 제거하기 때문에, 그 캐시 데이터를 받은 클라이언트는 문제가 발생할 수 있다.
  • 캐시가 모든 요청마다 원 서버와 재검사시켜 클라이언트로 가는 응답에 Set-Cookie 헤더 값을 기술해서 이 문제를 개선할 수 있다.
    • Cache-Control: must-revalidate, max-age=0

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

  • 요청이 Cookie 헤더와 함께 오면, 결과 콘텐츠가 개인정보를 담고 있을 수도 있다는 뜻이다.
  • 개인정보는 캐시되지 않도록 표시되어 있어야 하지만, 그 표시를 하지 않는 서버도 있다.
@vo0a vo0a changed the title [2부 11장] 클라이언트 식별과 쿠키 [3부 11장] 클라이언트 식별과 쿠키 Sep 18, 2022
@ruthetum
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants