CS 스터디 1주차 - 쿠키, 세션, 토큰

Lilac-_-P·2023년 4월 23일
0

HTTP 프로토콜

HTTP(Hypertext Transfer Protocol)는 인터넷상에서 데이터를 주고 받기 위한 서버/클라이언트 모델을 따르는 프로토콜이다.

웹 상에서 데이터를 주고받기 위해서는 HTTP 프로토콜을 사용하고, HTTP 프로토콜은 1991년에 최초로 제안되어, 현재는 HTTP/3 까지 발전하였다.

이번 발표와 관련된 HTTP 프로토콜의 가장 큰 특징 2가지는 아래와 같다.

  • Connectionless : 연결이 없음(연결을 유지하지 않음)
  • Stateless : 상태가 없음(상태를 유지하지 않음)

즉, 클라이언트가 서버에 요청을 보내고 서버가 클라이언트의 요청에 응답을 하는 순간 HTTP 연결은 끊어지며, 서버는 이전에 있었던 클라이언트와의 통신에 대한 정보를 기억하지 않는다.

웹 애플리케이션에서의 HTTP의 한계

대부분의 웹 애플리케이션은 여러 페이지(요청)에 걸쳐 흐름이 이어지기 때문에, 흐름이 이어지는 동안 해당 요청을 보낸 사용자를 식별해야할 필요성이 생긴다.

그런데, 위에서 언급한 HTTP 프로토콜의 특징 2가지가 이 부분에서 큰 걸림돌로 작용하게 된다. 연결/상태를 유지하지 않기 때문에 모든 요청들이 각각 독립적으로 취급되기 때문이다.

서버는 클라이언트로부터 오는 모든 요청을 어떤 흐름의 어떤 사용자로부터 오는 요청인지를 구분하여 각 사용자의 흐름에 맞는 응답을 해야하고, 클라이언트 또한 서버에게 자신이 어떤 흐름에 놓여있는 어떤 사용자인지 매번 요청이 보낼 때마다 알려야한다.

HTTP 프로토콜의 특성이자 웹 애플리케이션에서 약점으로 작용하는 Connectionless와 Stateless을 보완하기 위해서 쿠키와 세션이 제안되었다.

쿠키

쿠키는 클라이언트가 로컬 저장소에 저장하는 작은 데이터 파일로, 일반적으로 쿠키에는 서버가 보낸 서버와의 통신 과정에 필요한 클라이언트의 상태 정보가 들어있다. 클라이언트가 요청에 쿠키를 담아서 보내면, 서버는 사용자의 상태 정보를 받아서 이를 통신에 사용할 수 있다.

HTTP 통신에서 특정 서버에 종속적인 데이터를 보내야하는 경우, 쿠키는 HTTP 요청 헤더에 Cookie 헤더를 이용하여 전달된다.

세션

세션은 웹 애플리케이션에서 서비스의 흐름동안 같은 사용자로부터 들어오는 요청들을 하나의 상태로 보고, 그 상태를 일정하게 유지시키는 기술이다. 즉, 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 한다.

서버는 클라이언트의 요청을 어떤 사용자의 웹 애플리케이션 흐름에 속하는 요청인지를 구분하기 위해 별도의 데이터를 서버 측에 보관한다.

세션 기반 인증

쿠키와 세션을 이용하는 가장 일반적인 예시 중 하나는 세션 기반 인증을 이용한 로그인이다.

어떤 웹 서비스가 로그인된 사용자에게만 서비스를 제공한다고 할 때, 최초의 로그인 이후 클라이언트는 자신이 로그인된 사용자임을 서버에게 알리기 위해 서버와 약속된 정보를 매 요청시에 서버에 추가적으로 전달해야하고, 서버 또한 클라이언트가 보낸 정보를 토대로 어떤 사용자인지를 구별할 수 있어야 한다.

세션 기반 인증에서는 클라이언트가 서버에게 최초 로그인을 하게 되면, 서버측에서 로그인된 사용자의 정보와 세션ID라는 임의의 식별자를 매핑하여 별도의 저장소에 저장하고, 클라이언트에게는 세션ID 값을 돌려준다. 클라이언트에게 세션ID 값만을 돌려주는 이유는 서버에서 인증된 사용자의 정보를 이미 저장하고 있기 때문이기도 하고, 추후 설명할 쿠키의 한계 중 보안적인 이유 때문이다.

클라이언트는 이후 서버에게 요청할 때 세션ID를 요청에 담아 함께 보내게 되고, 서버는 클라이언트의 요청에 담긴 세션ID를 이용해 서버 내의 저장소에 저장해놓았던 인증된 사용자 정보를 찾음으로써, 이를 서비스 제공에 사용할 수 있다.

쿠키와 세션의 실사용 예시

쿠키

  • 크롬브라우저 - 개발자 도구 - 애플리케이션 - 쿠키

세션(자바 기준)

  • org.apache.catalina.session.ManagerBase 클래스
  • org.apache.catalina.session.StandardSession 클래스

쿠키와 세션의 한계

쿠키 : 클라이언트 로컬에 저장되기 때문에, 쿠키 데이터의 변조나 유출의 위험이 있다.
세션 : 서버 리소스를 사용하기 때문에, 서버의 부담이 커진다.

토큰의 등장

서버 리소스를 사용하는 세션 방식은 웹 애플리케이션의 동시 사용자가 많아지면 많아질수록 서버의 부담이 커지게 되고, 서버의 하드웨어 스펙을 넘어서 서버 리소스를 사용하게 되면 장애로 이어진다.

이런 세션의 한계점을 해결해보고자 제안된 기술이 토큰이다.
서버 측에 인증된 사용자 정보를 저장하는 대신, 토큰이라는 인증된 사용자 정보를 담은 데이터를 클라이언트에게 돌려주는 것이다. 서버는 이 토큰을 이용해서 클라이언트를 구분해야하기 때문에, 토큰은 클라이언트가 인증한 서버에서 밖에 만들지 못하는 토큰이어야만 한다. 따라서 일반적으로 토큰에는 암호학적인 처리가 되어있어, 해당 토큰을 발급한 서버에서만 이 토큰을 사용할 수 있다.

참고.
토큰에 적용되는 암호학적 처리는 전자서명

토큰 기반 인증

토큰 기반 인증도 세션 기반 인증처럼 최초의 로그인 이후 클라이언트는 자신이 로그인된 사용자임을 서버에게 알리기 위해 서버와 약속된 정보를 매 요청시에 서버에 추가적으로 전달해야하고, 서버 또한 클라이언트가 보낸 정보를 토대로 어떤 사용자인지를 구별할 수 있어야 한다.

토큰 기반 인증에서는 클라이언트가 서버에게 최초 로그인을 하게 되면, 서버측에서 로그인된 사용자의 정보와 암호학적 요소를 이용하여 서버 본인만 만들 수 있는 토큰을 생성하고, 클라이언트에게는 토큰을 돌려준다.

클라이언트는 이후 서버에게 요청할 때 토큰을 요청에 담아 함께 보내게 되고, 서버는 클라이언트의 요청에 담긴 토큰이 자신이 발급했던 토큰이 맞는지 검증한 후, 자신이 발급했던 토큰이 맞다면 토큰에 담긴 인증된 사용자 정보를 서비스 제공에 사용할 수 있다.

토큰 기반의 인증 경우, 토큰 자체에 인증된 사용자 정보가 들어있기 때문에 서버는 토큰을 따로 서버측에 저장할 필요 없고, 자신이 발급한 토큰이 맞는지만 검증하는 역할만 수행하면 된다.

토큰의 실사용 예시

JWT (JSON Web Token)

JWT는 웹에서 사용되는 JSON 형식의 토큰에 대한 표준 규격으로, 위에서 설명한 웹 상의 토큰 기반 인증에서 사용될 수 있는 토큰 규격이다.

JWT는 헤더(header), 페이로드(payload), 서명(signature) 세 파트로 나눠져 있으며, 아래와 같은 데이터들이 각 파트에 들어가 있다.

  • 헤더(Header) :어떠한 알고리즘으로 암호화 할 것인지, 어떠한 토큰을 사용할 것 인지에 대한 정보

  • 페이로드(Payload) : 토큰을 통해서 전달하려는 정보(사용자 id나 토큰 유효기간, 발급일자 등의 다른 데이터, JWT 에서는 이것들을 클레임이라고 부름)

  • 서명(Signature) : 서버가 해당 토큰이 자신이 직접 만든 토큰인지를 검증할 수 있게 하는 서명(서버가 갖고 있는 비밀키를 이용해서 생성함)

  • Reference : https://jwt.io/

토큰의 한계

한번 발급된 토큰을 서버측에서 추적하지 않는다. 서버는 클라이언트로부터 전달된 토큰의 유효성만을 검증할 뿐이다. 그러므로, 서버는 한번 발급된 토큰에 대해서 토큰의 무효화를 강제할 수 없다.

세션 기반 인증에서는 서버측에서 인증된 사용자에 대한 정보를 저장하고 있기 때문에, 해당 사용자에 대한 문제가 발생했을 때 서버는 서버 세션 저장소에서 해당 사용자에 대한 정보를 삭제하면 사용자로부터 전달되는 세션ID의 무효화를 강제할 수 있지만, 토큰은 이것이 불가능하다. (강제 로그아웃 같은 기능이 구현 불가능함)

세션 기반 인증 VS 토큰 기반 인증

뭐가 더 좋다고 말할 수 없다.
개발하고 있는 애플리케이션의 특성을 고려하여 적절한 인증 방법을 골라야한다.

주의.
세션 기반 인증에서의 쿠키로 전달되는 값이던, 토큰 기반 인증에서 토큰으로 전달되는 값이던,
사용자에게 민감한 정보가 쿠키 또는 토큰에 담기면 안된다.

profile
열심히 하자

0개의 댓글