들어가며

  • 이전 포스트에서 HTTP 헤더의 표현 헤더 및 여러 일반 헤더에 대해 알아보았다.
  • 이번 포스트에서는 인증과 쿠키의 개념에 대해 알아보도록 한다.

 

 

 

인증

  • 인증과 관련된 HTTP 헤더는 Authorization과  WWW-Authenticate 두개로 나누어진다.
  • Authorization은 클라이언트의 인증 정보를 서버에 전달하는 헤더이다.
  • WWW-Authenticate 헤더는 리소스에 접근 시 필요한 인증 방법을 정의한 헤더인데 일반적으로 어떤 리소스에 접근 요청을 보낼 때 401 - UnAuthorized 응답과 함께 사용된다.
    • 해당 헤더를 통해 클라이언트는 어떤 방식으로 인증을 수행하여야 하는지에 대해 알 수 있다.

 

 

쿠키

  • 쿠키와 관련된 헤더는 2개가 있는데 그 전에 쿠키의 필요성과 개념에 대해 먼저 알아보도록 하자.
  • 우리가 로그인 등의 인증이 필요한 사이트에 접속을 한다고 가정해보자. 우리가 로그인을 통해 인증을 성공했다. 그리고 다시 welcome page로 돌아가면 어떤 일이 발생할까?
  • 이전에 우리가 HTTP의 특징으로 보았던 무상태성(Stateless)을 기억하고 있다면 매우 당연하게도 서버는 우리가 인증을 성공했다는 정보를 모를 것이다. 왜냐면 로그인을 수행했던 연결이 아닌 새로운 연결로 서버와 통신하고 있기 때문이다.
    • 연결을 유지하게 하면 안되냐는 생각을 할 수 있으나 역시나 HTTP의 특징 중 하나인 비연결성(Connectionless)에 의해 부정되는 생각이다.
  • 하지만 우리가 저런 사이트를 이용할 때 로그인을 성공하고 나면 해당 사이트를 계속 돌아다녀도 인증을 수행했다는 정보가 서버에 들어가 있는 것처럼 동작한다. 어떻게 하면 이렇게 할 수 있을까?

인증 정보 유지 - 모든 요청에 사용자 정보 포함

  • 가장 단순한 방법으로 모든 요청에 사용자의 정보를 HTTP 메시지에 담아 서버로 보내는 것이다.
  • 서버는 해당 요청에 있는 사용자 정보를 읽고 사용자를 특정할 수 있을 것이다.
  • 문제는 이런 방식을 사용할 경우에 모든 요청과 링크에 사용자의 정보를 포함시켜 전송해야 한다는 번거로움이 존재한다. 또한 사용자의 정보가 필요하지 않는 요청이나 링크에도 사용자의 정보를 포함시켜야 할 수도 있다.
  • 또다른 문제로 만약 브라우저를 닫았다 다시 여는 상황에 대해서도 생각해야 한다.
    • 다시 브라우저를 연다면 이미 모든 사용자 정보들이 날아가 있기 때문에 사용자는 다시 서버에 인증을 수행해야 하는 번거로움이 존재한다.

인증 정보 유지 - 사용자의 pc 내에 사용자의 정보를 저장

  • 그 다음으로 사용자의 PC에 자신의 정보를 저장하는 하나의 저장소를 만들어 놓는 것이다.
  • 이런 방식을 사용할 경우에 모든 요청에 사용자 정보를 포함시킬 필요도 없다. 사용자의 정보가 필요하다면 그냥 저장소를 통해 사용자의 정보를 가져와 요청에 넣어주면 된다.
  • 브라우저를 닫았다가 다시 열어도 상관없다. 이 저장소는 PC 내부에 저장되고 있기 때문에 브라우저와는 독립적으로 데이터를 보관하기 때문이다.

쿠키와 쿠키 저장소

  • 위에서 논의했던 저 저장소가 바로 쿠키 저장소이다. 그리고 쿠키 저장소에서 불러온 정보를 쿠키라고 말한다.
  • 이제 이 쿠키와 쿠키 저장소를 사용해서 어떻게 사용자의 정보를 유지하는지에 대해 알아보자.
    • 클라이언트가 서버에 로그인을 통해 인증을 성공적으로 수행하였다면, 서버는 클라이언트에게 Set-Cookie 헤더를 통해 유저의 정보를 쿠키 저장소에 쿠키로 저장하라는 메시지를 보낸다.
    • 클라이언트는 해당 헤더를 통해 유저의 정보를 쿠키 저장소에 저장한다. 그리고 해당 사이트의 다른 페이지로 이동할 때 쿠키 저장소에서 해당 클라이언트 정보를 Cookie 헤더에 넣어 요청 메시지를 보낸다.
    • 이는 모든 요청에 쿠키 정보가 자동으로 포함되도록 함으로서 구현할 수 있는데 만약 쿠키 정보가 없다면 빈 값으로 넣어 보내주면 된다.
  • 이렇게 쿠키는 사용자의 로그인 세션 관리나 광고 정보를 트래킹할때 사용된다.
  • 또한 위에서 모든 요청에 쿠키 정보가 자동으로 포함되게 한다고 했는데 실제로 쿠키 정보는 서버에 항상 전송된다. 이는 곧 HTTP 메시지의 크기가 커진다는 것을 의미하고 추가적인 네트워크 트래픽을 유발시킨다.
  • 이러한 이유 때문에 쿠키는 최소한의 정보만을 사용하여 쿠키로 세팅해야한다. 쿠키의 정보가 크면 클수록 추가적인 네트워크 트래픽은 커지기 때문이다.

 

 

쿠키의 설정과 구성요소

  • Set-Cookie는 꽤 많은 구성 요소를 가지고 있는데 다음과 같은 Set-Cookie 헤더값을 보면서 알아보자.
set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure

 

  • sessionId는 현재 클라이언트가 인증을 한 세션의 ID식별을 의미한다.
  • 그 이외에 expires, path, domain, Secure가 존재하는데 하나씩 알아보도록 하자.

expires

  • expires 속성은 말 그대로 쿠키의 생명 주기를 말한다. 뒤에는 특정 날자가 붙는데 해당 시간이 되면 쿠키가 만료되어 삭제된다.
  • expires 말고도 초 단위로 쿠키의 생명 주기를 관리할 수 있는 속성이 있는데 max-age속성이 그렇다.
  • max-age=3600 라고 할 수 있으며 해당 속성을 추가할 시 쿠키의 생명은 1시간이라는 의미가 된다. 만약 0이나 음수 값을 넣는다면 즉시 삭제된다.
  • 만료 날짜를 생략할 시에 해당 쿠키는 브라우저가 종료되기 전 까지만 유지되며 브라우저가 종료되면 삭제된다. 이를 세션 쿠키라고도 한다.
  • 만료 날짜가 기입될 시에 쿠키는 해당 날짜까지 유지되게 된다.

domain

  • domain은 해당 쿠키가 어느 사이트에서 접근할 수 있는지를 나타내는 속성이다. 만약 명시적으로 설정할 경우에 명시한 도메인은 물론 그 서브 도메인까지 해당 쿠키에 접근이 가능하다.
    • 이때 서브 도메인은 메인 도메인에 추가적인 부분을 정의하는 말 그대로 부분 도메인을 말한다.
    • 예를 들어 domain=example.org라고 설정해 놓았다면 다음과 같은 도메인에서 쿠키를 접근할 수 있다.
      • example.org
      • dev.example.org
      • m.example.org
  • 만약 domain 부분을 생략한다면 현재 속해있는 도메인만 쿠키에 접근이 가능하다. 즉 내가 example.org에 접속해 있는데 domain을 생략했다면 현재 생성된 쿠키는 example.org만 접근이 가능하다는 것이다.

path

  • path는 입력된 경로를 포함한 그 하위 경로에 속한 페이지들만 쿠키에 접근이 가능하도록 제한한다.
  • 일반적으로 path=/ 로 루트로 지정한다. 왜냐면 루트를 포함하여 모든 페이지가 쿠키에 접근이 가능해지기 때문이다.
    • 예를 들어 path=/home 으로 설정했다면 다음과 같이 접근 가능한 경로와 그렇지 않은 경로가 나누어진다.
      • /home - 가능
      • /home/level1 - 가능
      • /home/level2/100 - 가능
      • /mypage - 불가능

보안 부분

  • 보안 부분은 xxx=yyy로 설정되는게 없어 따로 설명한다. Secure, HttpOnly, SameSite로 나누어진다.
  • Secure는 schema가 https 인 경우에만 쿠키를 전송하도록 하는 일종의 제한자이다.
    • 보통 쿠키는 https, http를 가리지 않고 전송하나 Secure를 통해 https연결일 때만 쿠키를 전송하도록 제한한다.
  • HttpOnly는 XSS 공격 방지를 위해 사용하는 속성으로 자바스크립트에서 해당 쿠키에 접근을 할 수 없도록 제한한다. 해당 속성은 http 전송에만 사용되며  https에서는 사용되지 않는다.
  • SameSite는 XSRF라는 공격을 방지하기 위해 넣는 것으로 해당 쿠키를 요청하는 도메인과 쿠키에 설정되어 있는 도메인이 동일한 경우에만 쿠키를 전송하도록 한다.
복사했습니다!