쿠키나 세션, 토큰을 쓰는 이유?
-
HTTP 프로토콜의 특징
- 비연결 지향(Connectionless)
- 클라이언트가 request를 서버에 보내고, 서버가 클라이언트에 요청에 맞는 response를 보내면 바로 연결을 끊는다.
- 상태정보 유지 안 함(Stateless)
- 연결을 끊는 순간 클라이언트와 서버의 통신은 끊나며, 상태정보를 유지하지 않는다.
-
쿠키와 세션의 필요성
- HTTP 프로토콜은 위와 같은 특징으로 모든 요청 간 의존관계가 없다.
- 즉, 현재 접속한 사용자가 이전에 접속했던 사용자와 같은 사용자인지 아닌지 알 수 있는 방법이 없다.
- 계속해서 연결을 유지하지 않기 때문에 리소스 낭비가 줄어드는 것이 큰 장점이지만, 통신할 때마다 새로 연결하기 때문에 클라이언트는 매 요청마다 인증을 해야 한다는 단점이 있다.
- 이전 요청과 현재 요청이 같은 사용자의 요청인지 알기 위해서는 상태를 유지해야 한다.
- HTTP 프로토콜에서 상태를 유지하기 위한 기술로 쿠키, 세션, 토큰이 있는것이다.
개념 정리
-
쿠키란?
-
개념
- 클라이언트 로컬에 저장되는 키와 값이 들어있는 파일
- 이름, 값, 유효 시간, 경로 등을 포함하고 있다.
- 클라이언트의 상태 정보를 브라우저에 저장하여 참조한다.
- key, value 형식
-
구성 요소
- 쿠키의 이름
- 쿠키의 값
- 쿠키의 만료시간
- 쿠키를 전송할 도메인 이름
- 쿠키를 전송할 경로
- 보안 연결 여부
- HttpOnly 여부
- http로만 통신이 가능하게 하고, 스크립트(javascript)에서 접근할 수 없게 함
- 크로스 사이트 스크립팅(XSS)공격으로부터 보호
- XSS 공격에서는 공격자가 악성 스크립트를 웹 페이지에 삽입해서 사용자의 쿠키 정보를 탈취할 수 있는데
HttpOnly
를 해놓으면 스크립트에 접근할 수 없음
- 그럼 무조건 HttpOnly가 좋나?
- JavaScript 스크립트를 통해 쿠키에 접근하고 조작할 때가 있어서 보안이 중요한 정보만 HttpOnly하면 됨
-
동작 방식

- client(웹 브라우저)가 서버에 요청
- 서버에서 상태를 유지하고 싶은 값을 쿠키로 생성
- 서버가 클라이언트로 응답할 때 HTTP 헤더(Set-Cookie)에 쿠키를 포함해서 전송
- 전달받은 쿠키는 웹브라우저에서 관리하고 있다가, 다음 요청 때 쿠키를 HTTP 헤더에 넣어서 전송
- 서버에서는 쿠키 정보를 읽어 이전 상태 정보를 확인한 후 응답
-
사용 예시
-
세션?
-
토큰이란?
-
개념
- 웹 서버가 클라이언트에게 제공하는 특정 자원에 접근하기 위한 권한을 나타내는
문자열
- 이 토큰을 통해 클라이언트는 서버의 자원에 안전하게 접근 가능
- 일반적으로 암호화된 문자열로, 서버가 클라이언트의 인증 후 해당 클라이언트에게 부여한다.
-
구성 요소
- 토큰의 값 : 고유한 암호화된 문자열
- 유효 시간
- 발행자 : 토큰을 발행한 서버나 서비스 식별
- 주체 : 토큰이 나타내는 사용자 또는 클라이언트 식별
- 권한 범위 : 토큰으로 접근할 수 있는 자원의 범위
-
동작 방식

- 웹 브라우저가 서버에 로그인 요청
- 서버는 클라이언트의 인증 정보를 화인하고 인증 토큰 생성
- 서버는 인증 토큰을 클라이언트에게 전송
- 클라이언트는 이후 서버에 요청을 보낼 때 이 토큰을 포함하여 전송
- 서버는 토큰을 검증하고 요청에 대한 권한 부여
-
예시
-
세션은 안전하고 효과적이지만, 요청마다 함께 딸려오는 세션 아이디를 바로바로 확인할 수 있도록 로그인한 사용자의 아이디를 메모리에 둔다.
-
메모리 공간을 차지하는 세션 방식의 대안은 토큰
을 발급해 주는 것.
정리
쿠키
- 클라이언트 측 저장 : 쿠키는 사용자의 브라우저에 저장
- 자동 전송 : 한 번 저장되면, 쿠키는 동일한 서버로의 모든 요청에 자동으로 첨부되어 전송
- 크기 제한 : 쿠키는 크기에 제한이 있다.
- 보안 취약성 : 쿠키는 클라이언트 측에 저장되므로 XSS와 같은 공격에 취약할 수 있다.
- 동일 출처 정책 : 쿠키는 동일한 출처의 요청에만 전송되는데, 크로스-도메인 이슈를 발생시킬 수 있다.
세션
- 서버 측 저장 : 세션은 서버에 사용자 정보 저장
- 상태 유지 : 사용자의 상태(로그인) : 서버에서 유지
- 보안성 : 세션 데이터는 서버에 저장되므로 쿠키보다 보안성이 높다
- 서버 부하 : 서버의 메모리를 사용하기 때문에, 사용자가 많을 경우 서버의 부하가 증가할 수 있다.
- 확장성 문제 : 로드 밸런싱 환경에서 세션을 관리하기 어려울 수 있다.
토큰(JWT)
- 상태가 없음(stateless) : 토큰은 서버에서 상태를 유지할 필요가 없다. 모든 정보는 토큰 자체에 인코딩되어 있다.
- 보안성 : 토큰은 암호화 및 signature를 통해 보안을 강화할 수 있다.
- 크로스 플랫폼 및 크로스 도메인 : 토큰은 다양한 플랫폼과 도메인 간에 유연하게 사용할 수 있다.
- 확장성 : 서버 측에서 상태 정보를 유지할 필요가 없으므로 시스템의 확장성이 높다.
💡 세션과 토큰의 차이점?
🗨️ 1. 세션은 별도의 메모리 공간을 가지고 client에서 받은 정보를 저장하지만 토큰은 별도의 메모리 공간이 필요없음(stateful vs stateless)
2. 세션도 쿠키 기반으로 세션을 생성한 포트가 아닌 다른 포트에서 해당 세션을 사용하려면 ‘세션 어피니티’ 와 같은 방법으로 처리해줘야하지만 토큰은 해당 작업이 필요없음(왜? 토큰은 다양한 포트에서 동일한 토큰 검증 로직을 구성하기만 하면 여러 포트에서도 사용할 수 있음)
💡 쿠키과 세션의 차이점
🗨️ 1. 세션은 별도의 메모리 공간을 필요로 한다.
2. 쿠키는 client에서 저장하고 세션은 server 쪽에서 저장한다. 그래서 세션이 쿠키보다 더 안전하다.
3. 쿠키는 용량이 제한되어 있다.(4KB) 세션은 서버에 저장되기 때문에 용량이 훨씬 크다.
4. 쿠키는 클라이언트에 문자열로 저장되어 있는 반면, 세션은 SESSIONID로 객체를 가져올 수 있다.
💡 토큰이 공격 받는 경우
🗨️ 토큰 스니핑 : 토큰이 안전하지 않는 네트워크 환경에서 전송될 때 발생한다. 해커가 네트워크 상에서 트래픽을 감시해서 토큰을 훔쳐서 사용자의 권한으로 인증된 요청을 수행한다.
토큰 예측 : 예측 가능한 토큰 값을 생성해서 공격자가 특정 사용자의 토큰을 예측해서 악용하는 공격이다.
토큰 노출 : 클라이언트 측 저장소(로컬 스토리지, 쿠키 등)에 저장되는 토큰이 악의적인 공격으로부터 노출될 경우 발생할 수 있는 취약점
💡 세션이 공격 받는 경우
🗨️ - 세션 무력화 : 악의적인 공격자가 사용자의 세션을 해제하고, 사용자를 유도해서 새로운 세션ID를 부여하여 해당 세션을 제어하려는 공격이다.