모든 개발자를 위한 HTTP 웹 기본 지식 : Header

jkky98·2024년 7월 8일
0

HTTP

목록 보기
2/7

HTTP Header

  • header-field : field-name:(OWS)field-value(OWS)
  • field-name은 대소문자 구분X

HTTP 전송에 필요한 모든 부가정보가 들어간다. 예로 메시지 바디의 내용, 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보... 필요시 임의의 헤더를 추가하는 것도 가능하다.

헤더의 분류는 General, Request, Response, Entity 헤더로 분류되었지만 2014년 RFC7230~35의 등장으로 엔티티(Entity)표현(Representation)으로 수정되었다. 표현은 표현 메타데이터와 표현 데이터로 구성된다.

  • 엔티티 헤더 -> 표현 메타데이터
  • 엔티티 본문 -> 표현 데이터

표현데이터에 해당하는 부분을 메시지 본문이라고 하며 이를 페이로드(payload)라 지칭한다.

표현(Representation)

Content-Type

표현 데이터의 형식을 설명하며, Content-Type: type/subtype; parameter와 같은 형식을 지닌다. 여기서 type과 subtype은 데이터의 형식을 지정하며, parameter는 선택적인 추가 정보이다.

Content-Encoding

표현 데이터 압축을 위해 사용하며 데이티를 전달하는 곳에서 압축 후 해당 인코딩 헤더를 추가하게 된다. 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축을 해제한다.(gzip, deflate, identity)

Content-Language

표현 데이터의 언어 종류를 설정한다.

Content-Length

표현 데이터의 길이를 나타내며 Transfer-Encoding 사용시 Content-Length를 사용하면 안된다.

web application framwork는 보톨 이러한 것을 자동으로 지원하는 경우가 많다. 자동으로 지정해주는 것과는 별개로 이것이 무엇인지 아는 것은 중요해보인다.

from django.shortcuts import render

def my_view(request):
    return render(request, 'my_template.html')

위의 코드에선 Content-Type: text/html; charset=utf-8를 자동으로 지정해주지만 만약 PDF 데이터 응답같은 경우는 다음과 같이 직접 지정해야할 수도 있다.

from django.http import FileResponse

def download_pdf(request):
    file_path = '/path/to/myfile.pdf'
    response = FileResponse(open(file_path, 'rb'), content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="myfile.pdf"'
    return response

Negotiation

  • Accept : 클라이언트가 선호하는 미디어 타입 전달
  • Accept-Charset : 클라이언트가 선호하는 문자 인코딩
  • Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
  • Accept-Language : 클라이언트가 선호하는 자연 언어

이러한 협상 헤더는 요청시에만 사용한다. Language를 기준으로, 만약 서버의 기본 자연언어 제공 설정이 en이라면 영어 데이터를 응답하겠지만 요청 HTTP에 Accept-Language가 ko로 되어있다면 요청의 의미는 "ko가 가능하면 ko를 줘"와 같다. 그러므로 만약 서버가 한국어 지원 가능한 서버라면 Content-Language를 ko로 넘겨줄 것이고, 그렇지 않다면 기본 디폴트인 en을 제공할 것이다.

만약 서버의 디폴트 Content-Language가 독일어라면?

한국인의 입장에서 Accept-Language는 ko로 요청하겠지만, ko가 없을 경우 디폴트인 de로 응답될 것이다. "한국어가 없다면 영어로 응답해줘"와 같은 조건적인 Negotiation도 가능하다.

협상과 우선순위(Quality Values(q))

우리는 위의 목적을 이루기위해 다음과 같이 요청 메세지를 만들 수 있다.

GET /event
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7

Quality Values(q)값을 사용하여 0~1 사이의 값을 자연언어마다 매칭시킨다. 클수록 높은 우선순위를 가지며 생략할 경우 가장높은 값인 1이 설정된다. 위의 예시에서 ko-KR은 1이다.

  • ko-KR, ko는 같은거 아닌가? : 맞다. 한국어를 쓰는 국가는 대한민국뿐이며, 대한민국은 한국어로 통일되어 있어 지역적 구분이 없으나 해외는 다를 수 있기 때문에 언어-지역, 언어 와 같이 같은 국가여도 여러가지가 존재할 수 있고 한국어의 경우는 위의 두 종류만 가지기 때문에 한국어를 1순위로 하고싶다면 위 두가지를 각각 1, 0.9로 설정하면 된다.
GET /event
Accept: text/*, text/plain, text/plain;format=flowed, */*

위는 미디어 타입의 negotiation이다. 이 경우에서도 우선순위가 적용되는데 그 기준은 구체성이다. 즉 구체적인 것이 우선된다. 예시로부터, text/plain;format=flowed가 1순위가 된다. 아마 마지막 순위는 */*이 될 것이다.

일반정보

  • From: 유저 에이전트의 이메일 정보 - 일반적으로 잘 사용되지 않음
  • Referer: 이전 웹 페이지 주소 - 유입경로 분석 가능, 많이 씀, 요청에서 사용
  • User-Agent: 유저 에이전트 애플리케이션 정보 - 클라이언트의 애플리케이션 정보, 통계 정보, 어떤 종류의 브라우저에서 장애 발생하는지, 요청에서 사용
  • Server: 요청을 처리하는 오리진 서버의 소프트웨어 정보 - 응답에서 사용
  • Date: 메시지가 생성된 날짜 - 응답에서 사용, GMT

특별한 정보

  • Host: 요청한 호스트 정보(도메인)
  • Location: 페이지 리다이렉션
  • Allow: 허용가능한 HTTP메서드
  • Retry-After: 유저 에이전트가 다음 요청을 하기까지 기다려야하는 시간

인증

  • Authorization: 클라이언트 인증 정보를 서버에 전달
    ex. Authorization: Basic xxxxxxxxxxxxxxx
  • WWW-Authenticate: 리소스 접근시 필요한 인증 방법 정의
  • 401 Unauthorized 응답과 함께 사용, WWW-Authenticate: Newauth realm="apps", type=1,
    title="Login to \"apps\"", Basic realm="simple"

쿠키

  • Set-Cookie: 서버에서 클라이언트로 쿠키 전달(응답)
  • Cookie: 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달

쿠키의 필요성은 HTTP의 Stateless를 이해하면 쉽게 이해할 수 있다. 만약 클라이언트가 로그인에 대한 자신의 ID와 pw를 포함하여 요청데이터로 서버의 로그인 엔드포인트로 전달했다면 서버는 로그인이 성공했다고 응답할 것이다. 이때 보통 쿠키에 로그인 정보를 담아준다. 그리고 클라이언트는 이것을 일정시간 보관하면서 인증이 필요한 요청에 항상 쿠키를 보내면서 로그인을 확인한다.

즉 쿠키는 클라이언트 입장에서 상태를 유지해주는 기술이다. 서버는 무상태로 설계되었기에 요청마다 인증정보를 확인해야하기 때문에 클라이언트는 어떻게 자신의 로그인정보를 잘 저장해야 하는지가 관건이기 때문이다.

모든 요청과 링크에 로그인정보 담기 -> Nope!!

URL은 사용자의 브라우저 히스토리에 기록된다. 따라서 민감한 로그인 정보가 브라우저 히스토리에 남아 있을 수 있으며, 다른 사람이 브라우저를 사용하거나 브라우저 히스토리를 확인하면 쉽게 접근할 수 있기 때문에 굉장히 위험하다. 하나 더 예시를 들자면 캐시의 경우 보통 URI를 Key로 캐싱을 진행하기 때문에 쿼리 파라미터로 로그인 정보를 전달할 경우 캐싱된 컨텐츠에 민감한 정보(ex.PW)가 포함될 수 있다.

쿠키의 특성

쿠키는 보통 로그인 세션 관리 그 이상의 정보들은 잘 보관하지 않는다. 쿠키 정보는 항상 서버에 전송되므로 네트워크에 추가 트래픽을 유발하기에 최소한의 정보만 사용해야한다. 만약 어떠한 데이터를 상태유지하고 싶다면 쿠키보다는 web storage(localStorage, sessionStorage)를 이용하도록 하자.

클라이언트단에서 상태유지에 활용되는 데이터들은 보안에 민감해서는 안된다.(개인 민감정보, 패스워드 등등)

쿠키의 생명주기는 Set-Cookie에서 설정되며 만료 날짜를 생략할 경우 브라우저 종료시 까지만 유지하고 만료 날짜를 입력하면 해당 날짜까지 유지된다(브라우저를 종료하더라도).

  • Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT
    • 만료일이 되면 쿠키 삭제
  • Set-Cookie: max-age=3600 (3600초)
    • 0이나 음수를 지정하면 쿠키 삭제

브라우저에는 여러 쿠키가 존재할 수 있어 Domain 정보를 쿠키에 입력하여 해당 도메인에서만 해당 쿠키들을 활용하게끔 설정할 수 있다. 예) domain=example.org -> 명시한 문서 기준 도메인 + 서브 도메인을 포함한다. 만약 domain= 지정을 하지 않는다면 쿠키를 생성했던 도메인에서만 쿠키를 접근한다.

또한 쿠키는 더 세부적으로 경로를 지정할 수도 있다. path=로 하여금 지정하며, 이 경로를 포함한 하위 경로 페이지만 쿠키접근이 이루어진다.

쿠키는 http, https를 구분하지 않고 전송되며 Secure를 적용할 시에 https인 경우에만 전송된다. HttpOnly를 통해 XSS 공격을 방지하고, 자바스크립트에서 접근을 불가능하게 만들 수 있다. 즉 HTTP 전송에서만 사용 가능하게끔 설정 가능하다.

XSS 공격

XSS(Cross-Site Scripting) 공격은 웹 애플리케이션의 취약점을 이용해 악성 스크립트를 삽입하는 공격 기법이다. 이를 통해 공격자는 다른 사용자의 브라우저에서 악성 스크립트를 실행하여 민감한 정보(예: 세션 쿠키, 사용자 입력)를 탈취하거나, 악성 행동을 수행하게 할 수 있다. HttpOnly를 사용한다면 스크립트가 쿠키를 다루는 것이 불가능해지므로 XSS에서 비교적 자유로워진다.

profile
펑크레코즈

0개의 댓글