포스트

stateless, stateful

stateless, stateful

  • stateless : 서버에서 HTTP와 같은 client의 이전 상태를 기록하지 않는 접속
  • stateful : 서버에서 client의 이전 상태를 기록
  • REST의 개념에서는 각각의 요청은 독립적인 stateless 방식이며 이것은 client가 상태정보를 모두 관리할 책임이 있다는 뜻이다
  • stateless는 caching, load balancing, scale out 이 장점이지만, 매 요청마다 상태 정보를 전달 받아야 하기 때문에 네트워크 자원을 소모하며, 서버는 정보를 처리하기 위한 작업이 필요하다
    • HTTP 프로토콜은 요청에 다른 응답을 받으면 연결이 끊어지고, 통신이 종료되면 어떠한 상태도 남지 않는다
    • 따라서 로그인 후 다시 웹 페이지에 접근하면 로그인 상태가 유지되지 않는 문제점이 있다.
    • HTTP 프로토콜의 인증 문제를 해결하기 위해 사용하는 방법으로 세션과 쿠기를 사용한다

세션

  1. 사용자가 서버에 로그인 request
  2. 서버는 request가 들어오면 DB를 쿼리하여 사용자 검증, 유효할 경우 고유한 ID 값을 부여하고 세션 저장소에서 저장한다. 이와 연결되는 세션 ID를 생성하여 response header에 포함시켜 response 한다
  3. 사용자는 서버에서 해당 세션ID를 받아 쿠키에 저장 한 후 제한된 요청에 접근할 때 마다 쿠키를 request header에 포함시켜 내보낸다
  4. 서버에서는 쿠키를 받아 세션 저장소에서 검증한 후 요청에 해당하는 데이터를 반환한다
세션의 특징
  • 쿠키(서버에 저장된 세션에 접근하기 위한 세션ID)가 HTTP 요청 중 노출되어도 쿠키 자체에 중요한 정보는 담겨있지 않다
  • 하지만 쿠키 자체를 훔쳐 세션에 접근하여 중요한 정보를 빼낼 수 있다.
  • 이를 막기 위해 세션에 유효시간을 넣거나 HTTPS를 사용하여 요청을 훔쳐도 그 안의 정보를 보기 힘들게 한다

  • 쿠키를 통해 세션에 접근하면 세션ID로 사용자를 구분할 수 있으므로 일일히 사용자 정보를 확인할 필요가 없다

  • 서버에 세션을 저장하기 때문에 사용자 수가 많아지면 서버의 부담이 늘어난다, 또한 서버의 확장성이 나빠진다
  • 서버의 사양 업그레이드 뿐만 아니라, 늘어나는 트래픽을 감당하기 위해서 여러 프로세스를 돌리거나 여러 대의 컴퓨터를 추가하는 것이 어렵다

  • 세션은 서버에서 가진 정보이며 쿠키는 사용자에게 발급된 세션을 열기 위한 ID이다
  • 인증의 책임을 서버에서 가지지 위해 사용자에게서 쿠키를 받아 세션을 가져온다
  • client의 HTTP 요청이 탈튀 당하여 쿠키가 해킹당한다면(세션 하이재킹 공격) 서버는 사용자를 오인하여 정보를 제공한다
    • 이것을 막기 위해 HTTPS 를 사용하거나 세션에 유효기간을 건다
  • 쿠키는 단일 도메인 및 서브도메인에서만 작동하도록 설계되어 있어 여러 도메인에서 관리하기 번거롭다.

토큰

  • 세션 기반 인증과는 달리 서버의 토큰을 이용하여 인증을 수행하는 방법
  • 세션 기반 인증의 stateful 서버는 클라이언트로부터 요청이 있을 때 마다 클라이언트의 상태를 유지한다.
  • 사용자가 로그인하여 인증을 요청하면 stateful 서버는 인증에 성공하였을 때 결과(세션)을 메모리 또는 DB에 유지하기 때문에 서버에 부하가 발생할 수 있다
  • 하지만 토큰 기반 인증은 stateless 서버를 사용하며 상태 정보를 유지하지 않는다
  • 서버가 전달받은 토큰을 검증만 하면 되기 때문에 서버의 부담을 줄이고 서비스의 확장성을 높일 수 있다

  1. 사용자가 로그인 request
  2. 서버는 request가 들어오면 사용자 검증을 통해 유효성을 확인하고 통과하면 토큰을 response와 반환한다
  3. 클라이언트는 토큰을 저장, 서버에 요청 시 토큰을 request header에 담아 서버에 요청
  4. 서버는 토큰을 검증 후, 요청에 응답
토큰의 특징
1. 모바일 앱 사용에 편리
  • 세션 기반 인증을 사용하면 쿠키 매니저를 따로 관리해야 한다.
  • 하지만 토큰을 사용하게 되면 웹 요청 API 헤더에 넣어서 사용을 하기 때문에 쿠키 매니저가 필요하지 않다.
2. CSRF 방지
  • 세션을 쿠키에 저장하여 사용하면
  • 사용자가 사이트를 벗어나도 이미 쿠키가 사용자 정보를 가지고 있기 때문에 공격자에게 노출 될 위험이 있다.
  • 공격자가 임의로 다른 URL을 유도하여 비밀번호를 바꾸거나 회원 탈퇴를 할 경우 쿠키가 있기 때문에 서버는 요청을 신뢰하고 작업을 수행한다
  • 이러한 문제를 해결하기 위해 탈퇴 시 비밀번호를 한 번 더 요구하거나, 토큰과 같은 credential을 포함한다
  • 하지만 토큰을 사용하면
  • 헤더 내 토큰이 포함되어 CSRF를 방지할 수 있다
3. 서버 확장 문제 해결
  • 여러개의 서버에서 한 세션이 첫 번째 서버에 생성되었다고 가정하면
  • 새로운 요청이 발생하고 그 요청이 다른 서버에 전달되면 해당 서버에는 세션 정보가 없으므로 unauthorized 응답을 받는다
  • stick세션(같은 서버에 세션을 계속 연결시키는 방식)을 사용하여 해결할 수 있다
  • 하지만 토큰을 사용하면
  • 요청 토큰은 모든 요청, 모든 서버가 가로채기 때문에 자연스럽게 이러한 문제가 해결된다
토큰 방식의 문제
  • sateless한 토큰의 특성 때문에 토큰을 강제로 만료할 수 없다
  • 토큰이 공격자에게 탈취되었다고 가정하면,
  • 공겨자는 토큰이 만료될 때 까지 서버에 요청을 할 수 있다.
  • 토큰 인증 방식의 단점을 보완하기 위해 토큰의 타입을 리프레시 토큰과 엑세스 토큰으로 나누어 사용하는 방식의 JWT 토큰을 사용하게 된다

JWT

  • Json Web Token은 인증헤더 내 사용되는 토큰 포멧이다.
  • 토큰은 base64로 인코딩한 string으로 이루어진다
  • 토큰은 두 개의 시스템끼리 안전한 방법으로 통신할 수 있도록 설계하는 것을 도와준다
JWT 장점
  • 계정 서버와 API 서버가 분리되어 있을 때 API 서버가 계정 서버에게 토큰의 유효성 여부를 물어보지 않고도 스스로 판단할 수 있다
  • Access Token은 단순하게 자원에 접근하는 Access Token이 아니라, 권한/인증에 대한 Token을 말한다
  • Refresh Token은 Access Token과 똑같은 형태의 JWT이며 Access Token의 탈취 문제를 해결하기 위해 발급하는 토큰이다
  • 처음의 로그인을 완료할 때 Access Token과 함께 발급되는 Refresh Token은 긴 유효시간을 가지면서 Access Token이 만료되었을 때 새로 발급해주는 열쇠가 된다

토큰과 세션의 차이

  • stateful 서버
  • 클라이언트에게 요청을 받을 때 마다 클라이언트의 상태를 계속해서 유지하고 이 정보를 서비스 제공에 이용한다.
  • 예를들어
  • 세션을 유지하는 웹 서버가 있다
  • 로그인을 하면 세션에 로그인이 되었다고 저장을 하고
  • 서비스를 제공할 때 해당 데이터를 사용한다
  • 세션은 서버의 메모리 또는 DB에 저장한다

  • stateless 서버
  • 상태를 유지하지 않는다
  • 서버는 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다
  • 클라이언트와 서버의 연결고리가 없기 때문에 서버의 확장성이 높아진다
  • 클라이언트가 고유 식별자를 가지고, 해당 식별자를 바탕으로 인증을 처리한다
    • 세션이 식별자에 대한 정보를 서버에 저장한다고 하지만 일부는 클라이언트에 저장한다. 보통은 쿠키로 저장한다
    • 세션은 그 식별자가 HTTP session에 한정된다는 점에서 토큰보다는 제한된 범위의 활용성을 가진다

  • 큰 흐름에서 세션은 기존의 웹 서비스에서 HTTP session을 기준으로 정보를 처리하였다
  • 토큰은 고유 식별자로 토큰을 만들어서 클라이언트에게 전달하는 방식으로 처리되어왔다
  • 따라서 토큰만 전달이 되면 다양한 포맷(json, xml) 구분없이 stateless로 폭 넓게 사용이 될 수 있다.
참고 사이트

해피 코딩!