쿠키(Cookie)와 세션(Session)
HTTP 프로토콜 특징
클라이언트 서버 구조
클라이언트가 서버에 요청(request)을 보내면, 서버는 그에 대한 응답(response)를 보냄
비연결 지향(Connectionless)
클라이언트의 요청에 응답한 후에는 연결을 끊음(연결 유지 X)
최소한의 자원으로 서버 유지
무상태(Stateless)
연결을 끊는 순간 클라이언트와 서버의 통신이 끝나고, 서버는 클라이언트의 상태 정보를 보존하지 않음
클라이언트가 요청할 때 필요한 데이터를 추가적으로 담아서 전송해야 함
항상 같은 서버를 유지하지 않아도 됨
응답 서버를 쉽게 바꿀 수 있어서 서버 확장성이 높음(무한한 서버 증설 가능)
쿠키와 세션의 필요성
HTTP 프로토콜의 특징으로 모든 요청 간에는 의존관계가 없음
현재 접속한 사용자가 이전에 접속했던 사용자와 같은 사용자인지 아닌지 알 수 있는 방법 존재 X
통신할 때마다 새로 연결하기 때문에 클라이언트는 매 요청마다 인증을 해야 함
로그인을 진행한 후, 다른 서비스를 사용하기 위해 매번 로그인(인증)을 하는 상황 발생
클라이언트의 상태 정보를 유지할 필요가 있을 경우,
쿠키
와세션
을 활용해서 Stateful한 동작 구현 가능무상태를 지향하기 위해 매 요청마다 필요한 정보를 담아 서버와 통신하는 경우, 비용과 부하가 커질 수 있음
쿠키(Cookie)
개념
클라이언트 로컬에 저장되는 키와 값이 들어있는 파일
사용자 인증이 유효한 시간 명시 가능(유효시간이 정해지면 브라우저가 종료되어도 인증 유지)
클라이언트의 상태 정보를 브라우저(로컬)에 저장하여 참조
구성 요소
쿠키의 이름(name)
쿠키의 값(value)
쿠키의 유효시간(Expires)
쿠키를 전송할 도메인 이름(Domain)
쿠키를 전송할 요청 경로(Path)
동작 방식
웹브라우저가 서버에 요청
상태를 유지하고 싶은 값을 쿠키(cookie)로 생성
서버가 응답할 때 HTTP 헤더(Set-Cookie)에 쿠키를 포함해서 전송
전달받은 쿠키는 웹 브라우저가 관리, 다음 요청 때 쿠키를 HTTP 헤더에 자동으로 넣어서 전송
서버에서 쿠키 정보를 읽어 이전 상태 정보를 확인 후 응답
사용 예
아이디, 비밀번호 저장
쇼핑몰 장바구니
세션(Session)
개념
일정 시간 동안 같은 브라우저로부터 들어오는 요청을 하나의 상태로 보고 그 상태를 유지함
웹 브라우저를 통해 서버에 접속한 이후부터 브라우저를 종료할 때까지 유지되는 상태
쿠키
를 사용하여 값을 주고 받으며 클라이언트의 상태 정보를 유지함사용자 정보 파일을 쿠키는 브라우저에 저장하고, 세션은 서버측에서 관리
사용자에 대한 정보를 서버에 두기 때문에, 사용자가 많아질수록 서버 메모리 많이 차지
보안 면에서 쿠키보다 우수
쿠키는 클라이언트 측에서 쉽게 탈취 가능
쿠키는 클라이언트 측에서 변경이 가능한 반면, 세션은 서버에서만 변경 가능
세션ID값 탈취는 적극적인 해킹공격으로 쿠키보다 어려움
동작 방식
웹브라우저가 서버에 요청
서버가 해당 웹브라우저(클라이언트)에 유일한 ID(Session ID)를 부여함
서버가 응답할 때 HTTP 헤더(Set-Cookie)에 Session ID를 포함해서 전송
웹브라우저는 부여된 Session ID를 쿠키에 저장해두고, 다음 요청 때마다 해당 쿠키를 HTTP 헤더에 넣어서 전송
서버는 Session ID를 확인하고, 해당 세션에 관련된 정보를 확인한 후 응답
로그인을 하는 경우, 해당 Session ID의 로그인 상태를 유효한 값으로 바꿔 저장
이후 요청에서 해당 Session ID를 가진 클라이언트는 로그인 상태가 유효하므로 별도의 로그인 없이 서비스 이용 가능
사용 예
로그인
다중 서버 환경에서 세션 관리
서버를 다중화했을 경우, 세션 불일치 이슈 발생
Sticky Session (스티키 세션)
클라이언트의 요청이 항상 해당 클라이언트의 세션이 저장된 서버로만 전달됨
로드밸런서에서 요청 쿠키(Session ID)를 읽고 지정된 서버(세션이 있는)로만 요청을 전달함
세션 정보가 없을 경우, 로드밸런서의 기본 알고리즘대로 요청 전달
Session Clustering (세션 클러스터링)
클러스터링: 병렬 처리해서 여러 대의 서버를 하나의 서버처럼 운영
세션을 서버 각각에 복사해서 모든 서버가 모든 세션을 보유하고 있음
특정 서버에서 세션이 생성될 때 다른 서버로 세션을 전파하여 복제
Session Storage (세션 스토리지)
세션만 관리하는 별도의 DB 서버를 두고, 모든 서버가 해당 서버를 참조함
토근 기반 인증 방식
세션은 사용자의 수 만큼 서버 메모리를 차지하기 때문에, 최근에는 이를 보완하는 토근 기반의 인증방식을 많이 사용함(
stateless
)ex)
JWT(JSON Web Token)
쿠키와 세션의 차이
저장 위치
클라이언트의 웹 브라우저가 지정하는 메모리 or 하드디스크
서버 메모리
저장 형식
Text
Object
만료 시점
쿠키 저장 시 설정
정확한 시점 알 수 없음
보안
클라이언트에 저장되므로 취약
Session ID만 저장하고, 이 값에 따라 서버에서 처리하므로 비교적 보안성 좋음
속도
클라이언트에 저장되어 서버에 요청 시 빠름
정보가 서버에 저장되어 있어 서버 처리가 필요해 쿠키보다 느림
용량 제한
한 도메인 당 20개, 한 쿠키당 4KB
제한없음
➕ 토큰
개념
메모리 공간을 많이 차지하는 세션 방식의 대안으로 사용자에게
세션 아이디
대신토큰
을 발급
동작 방식
클라이언트가 서버에 접속 시, 서버는 클라이언트에게 인증되었다는 의미로
토큰
부여 (해당 토큰은 유일함)클라이언트는 전달받은 토큰을 쿠키나 스토리지에 저장함
토큰을 발급받은 클라이언트는 다시 서버에 요청을 보낼 때 헤더에 토큰을 심어보냄
서버의 토큰 일치여부 체크로 인증과정 처리
클라이언트로부터 받은 토큰과 서버에서 제공한 토큰의 일치여부 체크
특징
적은 서버의 부담
토큰은 클라이언트에 저장 됨 → 세션을 관리했던 서버의 부담을 덜 수 있음
해당 서버만이 만들 수 있는 토큰 발급 → 상태를 저장하지 않고도 사용자의 정보 파악 가능
한계
한 번 발행한 토큰은 유효기간 만료시 까지 통제 불가
여러 기기에서 로그인 제한 불가
세션에 비해 토큰 정보 탈취 당할 가능성 높음
해결 방법으로
만료 시간
이용
토큰 자체 데이터 길이가 긺
인증 요청이 많아질 수록 네트워크 부하가 심해짐
JWT (JSON Web Token)
개념
인증에 필요한 정보들을
암호화
시킨 JSON 토큰JWT토큰을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식
특징
JWT는 JSON 데이터를 Base64 URL-safe_Encode를 통해 인코딩을 직렬화한 것
Self-contained
필요한 정보를 자체적으로 지니고 있음
Signature
전자서명을 통한 위변조 체크
토큰 내부에 위변조 방지를 위해 개인키를 통한 전자서명이 들어감
사용자가 JWT를 서버로 전송시 서버는 서명을 검정하는 과정을 거침
검증 완료 시 요청한 응답을 돌려줌
Calim
JSON 데이터 구조로 표현한 토큰
표준규약(RFC-7519)에 따라 생성된 암호화된 문자열(토큰)
URL-safe
두 개체 사이에서 손쉽게 전달되며, 사용되는 JSON 데이터는 URL에 포함될 수 있는 문자만으로 생성
HMAC 알고리즘 사용으로 비밀키 또는 RSA를 이용한 Public Key / Private Key 쌍으로 서명 가능
구조
.
을 구분자로 나누어지는 세가지 문자열의 조합Header
알고리즘과 토큰 타입을 포함
"alg" : 정보를 암호화할 해싱 알고리즘 지정
"typ" : 토큰의 타입 지정
Payload
토큰에 저장할 정보를 가짐
Claim형태(key, value로 이루어진 한쌍의 정보)로 이루어짐
Registered Claim
서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임
해당 클레임의 사용은 전부 선택적
Public Claim
충돌이 방지된 이름을 가지고 있어야함
충돌을 방지하기 위해 클레임 이름을 URI형식으로 생성
Private Claim
서버와 클라이언트, 서비스와 서비스간에 협의하에 사용되는 클레임
공개 클레임과 달리 이름이 중복되어 충돌 발생 가능
민감한 정보는 불포함 또는 암호화 처리가 필요
Signature
인코딩된 Header와 Payload를 더한 뒤 비밀키로 해싱하여 생성
토큰의 위변조 여부 확인 시 사용
Header 및 Payload는 단순 인코딩된 값으로 해커가 복호화와 조작 가능
Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화할 수 없음
토큰 인증 과정
클라이언트
가 서버로 로그인 요청을 보냄서버
는 검증 후 클라이언트 고유 ID등의 정보를 Payload에 담고, 암호화할 비밀키를 사용해 Access Token(JWT) 발급클라이언트
는 전달받은 토큰을 저장해두고, 서버에 요청할 때마다 토큰을 요청 헤더 Authorization에 포함시켜 함께 전달서버
는 토큰의 Signature 을 비밀키로 복호화한 다음, 위변조 여부 및 유효 기간 등을 확인 후 유효한 토큰이라면 요청에 응답
AccessToken
클라이언트에서 요청한 로그인이 성공한 경우, 서버는 AccessTocken 발급
사용자
발급받은 토큰 정보를 기억하고 있음
서버 호출시 헤더에 해당 토큰을 담아 호출
서버
AccessToken을 DB나 파일에 저장하지 않았으므로 미리 정의된 비밀키를 이용해 비교하여 인증 처리
이와 같은 이유로 서버는 특정 사용자의 접속을 강제로 만료시키기 어려움
RefreshToken
개념
한번 발급되면 만료기간까지 계속 사용가능하므로 탈취시 위험하다는 단점을 해결하기 위해 사용
Access Token, Refresh Token으로 이중으로 나누어 인증 진행
Access Token의 유효기간을 짧게 만들고, 유효기간이 만료될 때마다 Refresh Token을 통해 새로운 Access Token을 만듦
특징
클라이언트에서 로그인을 요청을 하고 성공을 할 경우, 기존 AccessToken 외에 추가로 RefreshToken을 발급
AccessToken 에 비해 긴 만료시간을 갖도록 설정
클라이언트 측
AccessToken이 만료되었을 시 추가로 받았던 RefreshToken을 사용하여 재발급 요청 진행
서버 측
유효한 RefreshToken이 오면 추가로 AccessToken 과 RefreshToken을 다시 발급
RefreshToken의 경우 서버 Storage에 따로 저장하며 이후 검증에 사용
이로인해 추가적인 I/O작업 필요하며 이는 별도의 I/O작업이 없다는 JWT의 빠른 인증처리의 특징에 상반되는 부분임
장점
토큰이 탈취되더라도 제한된 기간만 접근 가능
RefreshToken에 대한 만료 강제 설정 가능
단점
클라이언트는 AccessToken 만료시 갱신하는 로직을 구현해야 함
서버는 별도의 storage 필요
Ref
Last updated