[인증 보안 기초] HTTP, 쿠키, 세션, 토큰 💁‍♀️

kai6666·2022년 7월 28일
0

TIL. 웹개발

목록 보기
3/3

👉 HTTP

  • W3(월드 와이드 웹) 상에서 정보를 주고 받을 수 있는 프로토콜 (클라이언트-서버 모델)

HTTP 프로토콜에서 클라이언트는 서버에게 요청(request)를 보내고, 서버는 클라이언트에게 응답(response)를 보낸다. HTTP는 통신 규약이기 때문에 모든 요청과 응답은 HTTP 양식에 맞게 전송해야 한다.

HTTP 특징: Stateless

  • Stateless
    🗣 "치킨 주문할게."
    🖥 "오키."
    🗣 "순살로 해줘."
    🖥 "뭐?"

  • Stateful
    🗣 "치킨 주문할게."
    🖥 "오키."
    🗣 "순살로 해줘."
    🖥 "오키."
    🗣 "치즈볼도 추가해줘."
    🖥 "오키."

HTTP 통신의 특징 중 하나가 무상태성(Stateless)이다. 과거의 요청과 응답 상태를 관리하지 않기 때문에, 위의 예시처럼 과거의 요청을 기반으로 하는 현재의 요청을 처리할 수 없다.

상태를 유지하지 않기 때문에 서버의 CPU나 메모리 같은 리소스 소비를 억제할 수 있다는 이점이 있기도 하지만, 서버가 클라이언트를 식별할 수 없기 때문에 하나의 주문을 이어갈 수 없고 새로운 요청을 보낼 때마다 로그인이 풀린다.

이와 같은 문제를 해결하기 위해 쿠키라는 기능이 도입되었다.


👉 쿠키

인터넷을 하다보면 대부분의 사이트가 쿠키 사용을 허락해달라는 팝업을 띄운다. 또는 로딩 개선을 위해 쿠키와 캐시를 삭제하겠냐고 묻기도 한다. 이 쿠키가 바로 Stateless한 통신을 Stateful하게 해주는 역할을 수행한다.

쿠키는 요청과 응답에 쿠키 정보를 추가해서 클라이언트의 상태를 파악하게 해준다.

  • 최초 통신
    🗣 (요청 전달)
    🖥 (응답 전달 + 🍪)

  • 이후 통신
    🗣 (요청 전달 + 🍪)
    🖥 (응답 전달) ("전에 왔던 녀석이군...!")

최초 통신시 서버가 응답의 Set-Cookie라는 헤더 필드에 쿠키를 담아서 보낸다. 이 쿠키가 클라이언트에 남고, 이후 클라이언트가 요청을 보낼 때 자동으로 쿠키도 함께 보내진다. 서버는 요청 정보에서 쿠키를 확인해 현재 요청을 날린 클라이언트가 누군지 식별할 수 있고, 서버 상 기록을 통해 이전 상태를 알 수도 있다.


(크롬의 경우 개발자 도구를 열어서 Application 탭의 Cookies를 통해 현재 사이트에서의 쿠키를 확인할 수 있다.)

그러나 쿠키에도 단점이 존재한다.

  • 보안에 취약하다. 쿠키는 유출 및 조작할 수 있기 때문에 악용될 수 있다.
  • 웹 브라우저마다 쿠키에 대한 지원이 다르다.
  • 쿠키 사이즈가 커질수록 네트워크에 부하가 심해진다.

쿠키 옵션

Set-Cookie말고도 쿠키는 여러 옵션을 사용한다.

  • Domain
    Domain은 요청 URL이 http://naver.com 이라면 naver.com에 해당하는 부분이다. Domain을 통해 네이버의 쿠키를 다음에 전송하는 일을 방지할 수 있다.
  • Path
    Path는 세부 경로로, 요청 URL이 https://entertain.naver.com/home 이라면 /home에 해당하는 부분이다.
  • MaxAge or Expires
    쿠키의 유효 기간을 정하는 옵션이다. 쿠키는 탈취 될 수 있기 때문에 영구적으로 남기지 않고 유효기간을 설정해야 한다.
    - MaxAge : 쿠키가 몇 초 동안 유효한지 설정
    - Expires : 쿠키가 언제까지 유효한지 날짜 설정
    (Wdy, DD Mon YYYY HH:MM:SS GMT 혹은 Wdy, DD Mon YY HH:MM:SS GMT 형태로 설정한다.)
  • Secure
    이 옵션이 true일 경우, HTTPS 프로토콜로 통신하는 경우에만 쿠키를 보낼 수 있다. 이 옵션이 없다면 프로토콜 무관하게 쿠키를 보낼 수 있다.
  • HttpOnly
    이 옵션이 true인 경우, 자바스크립트에서 쿠키 접근이 불가하다. 디폴트 값은 false다.


👉 세션

쿠키에서 한 발 나아가, 세션을 기반으로 한 인증을 할 수도 있다. 위 이미지처럼 클라이언트가 로그인 요청을 보내면 서버가 응답의 쿠키에 세션 아이디를 함께 보낼 수 있다. 그럼 이 세션 아이디가 이후 통신 시 쿠키와 함께 다시 보내지기 때문에, 세션 아이디를 기준으로 클라이언트를 식별할 수 있다.

쿠키는 클라이언트가 보내는 쿠키를 서버가 식별만 하면 되는데, 세션 기반 인증 방식에서는 세션 정보를 저장할 필요가 있다. 이를 보통 세션 스토리지나 redis와 같이 트랜잭션이 빠른 DB에 담아둔다.

세션 기반 인증 방식의 장점은 다음과 같다.

  • 서버가 클라이언트의 웹 브라우저에 의존하지 않아도 된다.
  • 세션 아이디가 고유하게 부여되기 때문에 요청이 들어올 때마다 회원 정보를 확인할 필요 없다.

세션 기반 인증 방식의 단점은 다음과 같다.

  • 서버는 세션 아이디로 유저를 식별하기 때문에, 해커가 세션 아이디를 탈취해 유저인 척을 해도 서버는 모른다.
  • 서버가 세션 정보를 관리해야 하기 때문에, 요청이 많이 들어오면 서버에 부하가 생긴다.


👉 토큰


토큰은 암행어사의 마패 같이, 어떤 곳에 출입하거나 무언가를 이용할 때 나의 권한을 인증하는 수단이다. 세션 아이디랑 같은 거 아냐? 싶을 수 있지만, 토큰 기반 인증 방식과 세션 기반 인증 방식은 분명한 차이가 있다.

우선 위 이미지로 토큰 기반 인증의 동작 방식을 살펴보자면, 서버는 클라이언트의 로그인 요청에 대한 응답에 토큰(여기선 JWT)을 생성하여 보내준다. 이후 요청의 헤더에는 이 토큰 정보가 함께 실려온다. 서버는 토큰을 검증하고, 올바른 토큰일 경우 요청하는 것을 응답으로 전해준다.

세션 기반 인증과 같은 점은 인증 정보가 HTTP 헤더에 담아 전달된다는 정도이다. 세션 정보는 생성 후 서버 DB에 보관하는데, 토큰 기반 인증에서는 서버가 토큰을 생성해줄 뿐 이후 보관은 클라이언트 측에 맡긴다. 쿠키와 세션의 장점을 합쳐놓은 느낌이다.

그렇다면 이 토큰은 어떻게 생성되는가, 먼저 토큰의 구성요소를 살펴볼 필요가 있다. (이 글에서는 JWT 토큰만 다룹니다.)

토큰은 Header, Payload, Signature로 이뤄진다. 각 요소는 .으로 구분된다.

  • Header
    • 토큰의 종류
    • 서명시 쓸 알고리즘
  • Payload
    • 유저의 정보
    • 권한 정보
    • 필요한 데이터
  • Signature
    • 인코딩된 Header와 Payload가 완성되었다면, 비밀 키와 Header에서 지정한 알고리즘을 사용해 암호화
base64 인코딩 전 - Hello World :) 
base64 인코딩 후 - SGVsbG8gV29ybGQgOik=

Header와 Payload는 base64로 인코딩되는데, 이는 얼마든지 복호화할 수 있다. 때문에 비밀키와 알고리즘으로 암호화하여 복호화하기 매우 어렵게 만든다. 때문에 이 Signature로 토큰의 위변조 여부를 확인할 수 있다.

위의 정보들로 생성된 토큰은 클라이언트 측에 저장되고, 이후 요청을 보낼 때 헤더의 Authorization에 값으로 전달된다. 그럼 서버는 토큰의 Signature를 비밀 키로 복호화하여 올바른지 확인한다.

토큰 기반 인증 방식을 사용하면,

  • 서버가 토큰 해독만 하면 되기 때문에, 클라이언트 정보를 저장할 필요가 없다.
  • 세션 DB와의 연관성도 없기 때문에 인증의 단계가 줄어든다.
  • 요청이 많이 들어와도 서버가 각자 해독을 해서 인증을 할 수 있기 때문에 확장성이 우수하다.
  • 토큰의 Payload에 권한 정보를 담을 수 있기 때문에 권한 부여가 용이하다.

이정도면 토큰은 무조건 좋은 것 같지만, 아쉽게도 토큰도 단점이 있다.

  • Payload는 해독이 가능하다. 때문에 중요한 정보를 담지 않도록 주의해야 한다. (ex. password)
  • 토큰의 길이가 길수록, 인증 요청이 많을수록, 네트워크에 부하를 준다.
  • 토큰은 자동으로 삭제 되지 않는다.
    • 탈취 당해도 토큰은 만료될 때까지 계속 쓸 수 있기 때문에 손 쓸 방법이 없다.
      ( 쿠키, 세션 기반 인증은 서버에서 쉽게 처리할 수 있는데 토큰은 이게 안 된다.)

✨ 토큰 단점 보완법

만료 기한 짧게 설정하기

토큰은 탈취 당하면 만료 될 때까지 기다리는 것 외에 방법이 없기 때문에, 애초에 만료 기한을 짧게 설정하는 것이 좋다. 이는 제공하는 서비스에서 유저 편의가 중요한지, 보안이 중요한지에 따라 개발자가 선택해야 하는 영역이다.

Refresh Token 활용

토큰에는 두 종류가 있다. Access Token과 Refresh Token이다. Refresh Token은 Access Token을 갱신해주는 토큰인데, 이 두 토큰을 함께 쓰면 상대적으로 만료 기한이 긴 Refresh Token이 만료되기 전까지는 이것이 Access Token이 만료 됐을 때 알아서 재발급해준다.

그러나 Refresh Token을 쓴다는 것은 Refresh Token을 검증하기 위한 별도의 저장소가 있어야 함을 의미하고, 이에 따라 세션 기반 인증처럼 확인 과정이 생기는 것이라 장단이 있는 토큰이다. 이 역시 서비스와 개발자의 선택에 따라 사용된다.


참고자료

profile
성장 아카이브

0개의 댓글