본문 바로가기

카테고리 없음

쿠키, 세션과 JWT: HTTP의 단점 보완하기

HTTP 의 특징

1. 비연결지향(connectionless)
클라이언트가 서버에 요청(request)을 한 후 서버가 보낸 요청(response)을 받으면 서버와의 연결을 끊는다
2. 무상태성(stateless)
연결을 끊는 순간 서버와 클라이언트의 통신이 끝나며 상태 정보를 유지하지 않는다


쿠키(cookie)
클라이언트(브라우저) 로컬에 저장되는 데이터 파일이다
이 데이터 파일에는 클라이언트의 상태 정보를 나타내는 키-값(key-value)이 들어있다
Response Header Set-Cookie 속성을 설정해서 쿠키를 만들 수 있다
쿠키는 사용자가 따로 요청하지 않아도 브라우저가 Request Hearder에 넣어 자동으로 서버에 전송한다

쿠키의 구성요소
이름: 각각의 쿠키를 구별하는데 사용되는 이름
값: 쿠키의 이름과 관련된 값
만료시간: 쿠키의 유지시간
도메인명: 쿠키를 전송할 도메인
경로: 쿠키를 전송할 요청 경로
보안 연결 여부
HTTPOnly여부

 

 

쿠키의 동작 방식

1. 클라이언트가 페이지를 요청한다
2. 서버에서 쿠키를 생성한다
3. HTTP 헤더에 쿠키를 포함시켜 응답한다
4. 브라우저가 종료되어도 쿠키 만료 기간이 있다면 클라이언트에서 보관한다
5. 같은 요청을 할 경우 HTTP 헤더에 쿠키를 함께 보낸다
6. 서버에서 쿠키를 읽어 이전 상태 정보를 변경할 필요가 있을 때 쿠키를 업데이트하여 변경된 쿠키를 HTTP 헤더에 포함시켜 응답한다


쿠키의 사용목적
1. 세션 관리(Session Management)
로그인 정보, 접속 시간, 장바구니 등 서버가 알아야할 정보들을 저장한다
2. 개인화(personalization)
사용자마다 다르게 그 사람에 적절한 페이지를 보여줄 수 있다
3. 트래킹(tracking)
사용자의 행동과 패턴을 분석하고 기록한다

쿠키 종류
session cookie - 만료시간 설정, 메모리에만 저장, 브라우저 종료 시 쿠키를 삭제한다
persistent cookie - 장기간 유지, 파일로 저장되어 브라우저 종료와 관계없이 사용할 수 있다
secure cookie - HTTPS 에서만 사용, 쿠키 정보가 암호화되어 전송한다
third-party cookie - 방문 도메인과 다른 도메인의 쿠키/광고 배너등 관리시 유입 경로를 추적하기 위해 사용한다

세션(Session)
쿠키 기반
웹 서버에서 웹 컨테이너의 상태를 유지하기 위한 정보를 저장한다
웹 서버에 저장되는 쿠키(session cookie)이다
서버에서 클라이언트를 구분하기 위해 세션 ID를 부여한다
웹 브라우저가 서버에 접속에서 브라우저를 종료할 때가지 인증상태를 유지한다
접속 시간에 제한을 두어 일정 시간 응답이 없으면 정보가 유지되지 않게 설정한다
-> 사용자에 대한 정보를 서버에 두어 쿠키보다 보안에 좋다
단점: 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다
-> 동시접속자가 많을 경우 서버에 과부하를 주허 성능이 저하될 수 있다

세션의 동작 방식

1. 클라이언트가 서버에 접속시 세션 ID를 발급 받는다
2. 클라이언트는 세션 ID에 대해 쿠키를 사용해서 저장하고 갖고 있다
3. 클라이언트는 서버에 요청할 떄 이 쿠키의 세션 ID를 같이 서버에 전달해서 요청한다
4. 서버는 세션 ID를 전달 받아서 별다른 작업없이 세션ID로 세션에 있는 클라이언트 정보를 가져와서 사용한다
5. 클라이언트 정보로 서버 요청을 처리하여 클라이언트에게 응답한다

 


세션의 특징
각 클라이언트에게 고유한 ID를 부여한다
세션 ID로 클라이언트를 구분해서 클라이언트의 요구에 맞는 서비스를 제공한다

세션 사용예
보안 상에 중요한 작업을 수행할 때 사용한다 - 로그인

쿠키 Vs 세션

1. 세션도 결국 쿠키를 사용한다 
-> 비슷한 역할을 한다

2. 사용자 정보가 저장되는 위치가 다르다 
쿠키는 클라이언트 브라우저, 세션은 서버의 자원을 사용한다

3. 보안에는 세션이 유리하다
쿠키는 클라이언트 로컬에 저장되기 때문에 데이터가 변질되거나 request에서 스니필 당할 우려가 있어서 보안에 취약하다
세션은 쿠키를 이용해 session ID만 저장하고 그것으로 구분해서 서버에서 처리한다 - 보안이 좋다

4. 쿠키도 만료시간이 있다 - 파일로 저장되어 브라우저를 종료해도 정보가 남아있을 수 있다
만료기간이 길 경우 쿠키삭제 시까지 유지될 수 있다
세션도 만료시간을 정할 수 있지만 브라우저가 종료되면 만료시간에 관계 없이 삭제된다

5. 쿠키에 정보가 있어 서버에 요청시 요청 속도가 빠르다
세션은 정보가 서버에 있어 처리가 요구되어 비교적 속도가 느리다


쿠키를 사용하는 이유
세션은 서버의 자원을 사용한다 - 서버의 메모리가 감당할 수 없거나 속도가 느려질 수 있다
자원 관리 차원에서 쿠키와 세션을 적절한 요소 및 기능에 병행 사용하여 서버 자원의 낭비를 방지하며 속도를 높일 수 있다

캐시와 쿠키/세션
캐시는 이미지나 css, js파일 등을 브라우저나 서버 앞단에 저장해놓고 사용한다
캐시에 저장되면 브라우저를 참고한다 - 서버에서 변경되어도 사용자는 변경되지 않는 것처럼 보인다
캐시를 지워주거나 서버에서 클라이언트로 응답을 보낼 떄 header에 캐시 만료시간을 명시할 수 있다
라이프사이클이 다른 것

토큰(JWT/Jason Web Token): 인증에 필요한 정보들을 암호화시킨 JSON 토큰
Base64 URL-safe encode 를 통해 인코딩하여 직렬화한 것이다
*Base64 URL-safe Encode: 일반적인 Base64 Encode에서 URL 에서 오류없이 사용하도록 +/-를 각각 -, _로 표현한 것이다
위변조 방지를 위해 개인키를 통한 전자서명이 들어있다

SWT(Simple web token) 및 SAML(Security Assertion Markup Language)과 비교할 때 JWT를 사용하면 이점이 있다
1. More compact : JSON 으로 인코딩한다 - XML로 인코딩하는 SAML 토큰보다 작다
2. More Secure : JWT는 공개키와 개인키를 나누어 서명이 가능하다
HMAC 암호 알고리즘을 사용하여 암호화된 서명도 가능하다
3. More Common : JSON의 object는 일반적인 프로그래밍 언어이기 때문에 접근성이 좋다
4. Easier to process : JWT는 인터넷 규모로 사용된다 모바일에서 처리가 더 쉽다

 

 

JWT 구조
토큰은 1. 헤더, 2. 페이로드, 3. 서명 세 파트로 구분된다

1. 헤더(Header)
JWT를 검증하는데 필요한 정보를 가진 JSON 객체: Base64 URL-safe 인코딩된 문자열이다
헤더는 JWT를 어떻게 검증하는가에 대한 내용을 담고 있다
alg는 서명시 사용하는 알고리즘이며 kid 는 서명시 사용하는 키(public/private key)를 식별하는 값이다

2. 페이로드(payload)
JWT의 내용이다 
페이로드의 속성들 - 클레임 셋(claim set)이라고 부른다
jwt에 대한 내용이나 클라이언트와 서버 간 주고 받기로 한 데이터들로 구성된다

3. 서명(Signature)
점(.)을 구분자로 헤더와 페이로드를 합친 문자열을 서명한 값이다
서명은 헤더의 alg에 정의된 알고리즘과 비밀 키를 이용해 생성하고 Base64 URL-Safe로 인코딩한다


토큰의 장점
header와 payload를 가지고 signature를 생성ㅎ하므로 데이터 위변조를 막을 수 있다
인증 정보에 대한 별도의 저장소가 필요 없다 -> 서버 부하가 줄어든다
JWT는 토큰에 대한 기본 정보와 전달할 정보 및 토큰이 검증되었다는 서명 등 필요한 모든 정보를 지니고 있다
토큰은 한번 발급되면 유효기간이 만료될 때까지 계속 사용이 가능하다

토큰의 단점
쿠키나 세션과 다르게 JWT는 토큰의 길이가 길어 인증 요청이 많아질수록 네트워크 부하가 심해진다
payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보를 담으면 안된다
토큰 탈취당하면 대처가 어렵다
특정 사용자의 접속을 강제로 만료하기 어렵다 // 반면 쿠키/세션 기반 인증은 서버 쪽에서 쉽게 세션 삭제 가능하다

토큰 보안 전략
1. 짧은 만료 기한 설정
토큰의 만료 시간이 짧으면 탈취되더라도 금방 만료되기 때문에 피해를 최소화할 수 있다
사용자가 자주 로그인해야하는 불편함이 있다

2. Sliding Session
예를 들어 로그인하고 글을 작성하는 도중 토큰이 만료되면 저장 작업이 정상적으로 작동하지 않고 작성한 글이 날아가는 일이 생기는 등 불편함이 존재한다
서비스를 지속적으로 이용하는 클라이언트에게 자동으로 토큰 기한를 늘려주는 방법이다
짧은 만료 기한의 단점을 보완한다

3. Refresh Token
클라이언트가 로그인할 때 Access Token 및 Refresh Token 을 함께 발급한다
Refresg Token 은 Access Token보다 만료기한이 길다
클라이언트가 요청을 보냈는데 Access Token이 만료되었을 때 Refresh Token을 이용하여 Access Token의 재발급을 요청한다
이때 서버는 Refresh Token을 복호화 후 유효하면 Access Token을 발급한다(Refresh Token도 만료된 경우라면 사용자에게 로그인을 요구한다)
Access Token의 만료 기한을 짧게 설정하여 1. 짧은 만료 기한 설정 전략처럼 탈취되더라도 빠르게 만료될 수 있다
또한 짧은 만료 기한에도 불구하고 자주 로그인을 할 필요가 없어진다
단점: Refresh Token이 공격자에게 탈취당할 경우 해당 공격자가 토근을 계속 refresh하며 사실상 기한 제한없이 로그인을 유지할 수 있다

4. Refresh Token + Session Storage
refresh token의 payload를 캐시서버(또는 세션 스토리지)에 저장한 후 refresh 요청 시 서버 측에 저장된 refresh token의 payload 와 일치여부를 검사하는 방식이다
이를 통해 사용자 로그아웃/공격자 토큰 탈취 시 서버 측에 저장된 refresh token의 payload를 제거하여 추후 refresh 요청 시 검사를 실패하도록 할 수 있다
장점(보안): 세션과는 달리 redis(등의 세션 스토리지)에 저장된 payload만으로는 토큰화(tokenizing)할 수 없기에 이 서버가 유출되더라도 클라이언트로의 위장이 불가하다
세션과 마찬가지로 서버에 부하가 걸릴 수 있다