우선 설명하기 앞서 무상태 프로토콜에 대해서 간략히 알아보았다.
무상태 프로토콜
Http는 기본적으로 무상태이며, 이전에 들어왔던 요청이나 로그인 여부에 관한 정보를 서버에서 기억하지 않는다.
서버가 정보를 저장하고있지 않기때문에 요청 하나하나가 독립적이게 되어 더욱 단순한 시스템 설계라는 장점이있지만
요청을 보낼때마다 매번 인증정보를 전달해야하며 로그인 상태 등의 정보들을 유지/관리가 번거롭다.
따라서 무상태인점을 보완하기 위해서
- 세션 - 서버가 사용자 상태 저장
- 쿠키 - 클라이언트가 상태 저장
- JWT - 토큰에 상태를 저장해 클라이언트가 가지고 있음
이 세가지를 통하여 인증 및 상태저장 및 관리를 하는것이다.
🤔상태 저장이란 뭘 의미하는걸까
무상태인 프로토콜 대신 세션,쿠키,JWT 등에 사용자의 정보와 인증, 활동기록들을 유지하고 기억한다는것을 의미한다.
지금부터 이 세가지에 대해서 차례대로 동작 방식을 알아보겠다.
◾세션
세션이란
클라이언트와 서버간의 상태를 유지하기 위해 다양한 정보 를 서버에 저장할 수 있다.
세션에 저장할 수 있는 것
1. 로그인 여부, 사용자 정보, 권한, 인증 정보를 저장하여 로그인한 사용자의 상태를 기억한다.
2. 비로그인 상태의 임시 데이터 저장 (장바구니,찜등을 비회원 상태에서도 가능하다고할때) 저장할 수있다.
3. 브라우저 정보, 마지막 접속 기록 등 사용자의 환경 정보를 기억하여 매요청마다 환경을 조회하지않아도되서 속도와 리소스를 절약한다. 또한 일관된 사용자의 환경 정보를 유지할 수 있게된다.
요청이 들어올 시 서버에서는 SessionID 를 생성하여 Cookie에 저장을 한다.
그 이후 요청을 보낼 때 Cookie 에 저장된 세션 아이디와 함께 보내 로그인 상태와 임시데이터를 조회할 수 있다.
그러나 모든 요청에 SessionID 를 생성하고 조회하는것은 아니다
요청분류 | 감지 (Spring Security) | 동작 |
로그인 | POST /login 으로 들어올 경우 감지 | 세션ID를 생성한다. |
로그아웃 | POST /logout 으로 들어올 경우 감지 | 세션ID를 지운다. |
인증 필요 요청 | Security Config에서 로그인한 사용자만 접근하도록 설정한 URL | 세션ID를 조회한다. 인증정보가 있는 경우 성공 없는 경우 실패되어 401 반환 (로그인을 요청하도록 할수있음) |
일반 요청 | 인증이 필요없이 접근 가능하도록 설정한 URL | 세션ID를 조회 하지않는다. |
세션의 장점
- 무상태 프로토콜이지만 서버에 사용자의 인증 정보나 상태 , 임시데이터를 저장할 수 있게되어 정보를 유지할 수 있다.
- 서버가 직접 관리하기 때문에 클라이언트 상에서 조작할 수 없어 비교적 안전하다.
세션의 단점
- 세션 하이재킹, 또는 자동으로 쿠키가 전송된다는 점때문에 CSRF 에 취약하다 이점은 쿠키에서 보완점을 적겠다.
- 서버에 많은 세션 정보를 가지게 될 경우에 복잡해질 수 있다. (무상태 프로토콜의 장점이 사라짐)
◾ 쿠키
쿠키란
웹 브라우저와 서버 사이에서 상태 정보를 저장하고 주고 받기 위해서 사용되는 데이터 조각이다.
주로 SessionID나 로그인 상태 유지 등에 사용되며
서버에서 Set-Cookie에 정보를 저장하게 될 경우에 HTTP로 요청 시 헤더에 쿠키를 담아 서버로 보내게 된다.
쿠키로 할 수 있는 것
1. 세션관리
로그인 시 쿠키에 JSESSIONID 라는 이름으로 SessionID가 저장된다.
이 SessionID를 쿠키가 관리하여 로그인 이후 요청시에 헤더에 쿠키를 실어보내 사용자 정보를 인증할 수 있게된다.
2. 비로그인 일때의 임시 정보 저장
비회원일 경우에도 장바구니나 방문기록등을 저장할 때에도 Cookie에 저장하는 방법을 쓸 수 있다.
또한 이러한 데이터를 쿠키가 가지고 있다가 로그인 하여 SessionID 가 생성될 경우에는
현재 장바구니에 담긴 것들을 새로 생성된 SessionID의 사용자에게로 저장시키는 등의 기능을 할 수 있게된다.
쿠키의 장점
- 쿠키는 클라이언트에 저장되기 때문에 서버에 별도로 저장공간이 필요없으며 메모리를 차지하지 않는다.
- 자동으로 HTTP 헤더에 추가가 되기 때문에 직접 헤더에 추가할 필요가 없다.
쿠키의 단점
1. HTTP을 사용할 경우 중간자 공격에 당할 수 있다
HTTP로 요청을 보낼 경우 암호화 되지않고 데이터가 평문으로 헤더에 포함되어 전송된다
따라서 네트워크에서 데이터가 그대로 흘러 가기때문에 이를 중간에서 가로채서 데이터를 볼 위험이있다.
네트워크에서 중간에 가로채는 행위를 패킷 스니핑 이라고한다.
이러한 점을 방지하기 위해 HTTP가 아닌 HTTPS를 사용하는것이 좋다.
HTTPS는 SSL/TLS 프로토콜을 사용하여 암호화된 데이터가 헤더에 포함되어 전송된다.
따라서 네트워크에서 중간에 가로채진다 하더라도 암호화되어있기때문에 안전하다.
2. XSS 공격에 취약하다.
XSS란 악성 스크립트를 사용자 몰래 삽입하여 쿠키를 탈취하는 공격행위를 뜻한다.
쿠키는 document.cookie 를 통해 자바스크립트로 쉽게 가져올수있다.
따라서 웹 사이트에 이러한 악성 스크립트를 넣어 사용자가 페이지에 접속을 하게 될 경우
공격자 서버로 쿠키의 값을 전송하도록 할 수 있다.
탈취한 쿠키를 통해서 하이재킹이나 계정 해킹등의 문제가 일어날 수 있다.
이러한 점을 방지하기 위해 HttpOnly 쿠키 옵션을 잘 설정해주어야한다.
Cookie.setHttpOnly(true);
HttpOnly를 true로 설정해줄 경우에 JS에서 접근이 불가능하다.
따라서 document.cookie로 쿠키를 불러올 수 없기때문에 XSS를 방지할 수 있다.
3. CSRF 공격에 취약하다.
CSRF 란 사용자가 웹사이트에 접속하였을때 로그인을 한 상태에서 공격자의 페이지에 접속을 하였을 때
공격자가 만들어놓은 악성 웹사이트나 스크립트가
사용자가 의도치 않은 요청을 특정한 웹사이트로 보내게 하는 공격행위이다.
이 공격으로인해 의도치 않은 계좌 이체나 개인정보를 유출등 심각한 보안 문제들이 발생할 수 있다.
이런 공격이 가능한 이유로는
쿠키가 요청될때 사용자의 의지와 관계 없이 자동으로 포함된다는 특징이있다.
로그인만 하였다면 공격자의 요청에도 자동으로 쿠키가 포함된다.
또 웹 서버는 HTTP 요청이 어디에서 왔는지에 대한 출처를 철저히 검사하지 않는다.
따라서 공격자의 페이지에서 보낸 요청이라도 정상적으로 요청이 처리된다.
이러한 두 특징때문에 CSRF에 취약하다.
이러한 점을 보완하기 위한 방법
1. CSRF 토큰 생성
사용자가 로그인하고 방문할때마다의 세션 마다 랜덤한 CSRF 토큰을 생성하여 쿠키가 자동으로 전송될때 같이 전송한다.
서버에서 CSRF 토큰 값과 세션ID 안에서 꺼낸 CSRF 토큰 값을 비교하여 대응되지 않는 경우 CSRF 위조 공격으로 판단하고 차단한다.
따라서 공격자의 페이지에 들어가게 된 경우
본래의 로그인한 페이지에서 생성되어 쿠키의 담긴 세션ID와 공격자 페이지에서 생성된 CSRF 토큰값이 같이 보내질 경우
둘의 값은 다르게 된다.
2. SameSite 쿠키 속성 설정
SameSite 설정을 통해서 타 도메인에서 오는 요청을 받지않도록 할 수 있다.
SameSite : strict 속성 - 완전히 일치하는 도메인의 요청만 처리한다.
SameSite : Lax 속성 - 안전한 Get 요청만 허용하며 그외에 요청은 제외한다.
3. CORS 정책 활용
.allowedOrigins("http://54.180.195.59:3000","http://54.180.195.59:8080","http://54.180.195.59")
서버에서 어떤 출처의 도메인을 허용할지 직접 지정할 수 있도록 설정한다.
◾ JWT
웹 브라우저와 서버 사이에서 사용자를 인증할 때 토큰을 사용하여 인증하는 방식이다.
세션의 경우 사용자 인증 정보를 서버에 저장하게된다.
그러나 JWT의 경우 웹 브라우저 상에서 토큰의 형태로 사용자 인증 정보를 저장하고 관리하게 된다.
JWT의 구조
jwt는 Header Payload Signature 으로 총 세가지의 구조로 이루어져있다.
1. Header
Header는 JWT의 첫번째 부분으로 typ , alg 으로 이루어진 JSON 객체이다.
- typ : jwt 토큰의 타입
- alg : 토큰 서명에 사용된 알고리즘
토큰 검증시 헤더의 정보를 참고하여 올바른 방식으로 서명인증을 진행 한다.
2. Payload
JWT의 두번째 부분으로 토큰의 담고싶은 실제 정보들을 담는 곳이다.
사용자의 정보, 권한, 토큰 만료시간등이 저장되는 것이며
토큰 인증에 성공할 경우 토큰을 통해 Payload에 저장된 실제 정보들을 Claims 객체 형태로 꺼내게 된다.
3. Signature
JWT의 세번째 부분으로 토큰의 무결성과 진위를 보장하는 역할
header에 들어갈 서명 알고리즘 정보와 비밀키를 통하여 서 Signature을 생성한다.
변조 위험을 방지하게 위해 생성하며
Header와 payload 가 변조되지않았음을 보장하고 서버만 알고있는 비밀키를 사용하여 만들어졌기때문에 안전
동작 순서
1. 사용자가 로그인 요청
서버에서 로그인 데이터를 통해 사용자를 검증하고 AccessToken과 RefreshToken을 생성한다.
2. 생성된 토큰 처리
RefreshToken은 DB와 Cookie에 저장
AccessToken 은 클라이언트로 전송한다.
3. 클라이언트 측 토큰 처리
AccessToken은 클라이언트측으로 전달 되어 localStorage 또는 sessionStorage에 저장하여 이후 인증 요청에 실어 보내게된다
4. 클라이언트에서 요청 시 토큰 전달
사용자 인증이 필요한 요청의 경우 Header에 AccessToken을 담아 서버로 전달한다.
5. 토큰 검증
서버에서는 전달 받은 토큰을 통해 서면 검증 혹은 만료 확인 등의 절차를 통해 토큰이 유효한지 검사한다.
토큰이 유효할 경우 정상적으로 요청을 처리하며
토큰 검증의 실패할 경우 401 에러를 반환한다.
토큰의 만료기간은 30분으로 만료 될 시 RefreshToken을 통해 재발급 받도록 한다.
6. RefreshToken 을 통한 토큰 재발급 요청
쿠키에 저장된 RefreshToken을 요청에 실어 전달한다.
7. RefreshToken 검증
AccessToken과 같은 검증 과정을 거치며 유효할 경우
AccessToken만 재 생성하여 클라이언트로 전달한다.
검증의 실패할 경우 (DB 존재 안함 & 토큰 만료) 똑같이 401 에러를 반환하여 로그아웃 처리하도록 한다.
이때 SessionStorage, DB , Cookie 에 저장되 있던 모든 토큰 정보들은 전부 소멸된다.
JWT의 장점
- 서버가 상태를 저장하지 않아도 되기때문에 서버측에 메모리 부담을 덜 수 있다.
- 토큰 자체에 사용자 정보, 권한, 토큰 기한 등이 저장되어있기때문에 별도의 DB 조회없이 인증할 수 있다.
JWT의 단점
1.토큰 탈튀 시 만료될때까지 악용될 수있다. 토큰 자체에 권한이 있기때문에 탈취 시 피해가 클 수 있다.
HTTP환경일 경우 중간자 공격에 취약하며 JWT 토큰이 암호화되지않은 상태로 브라우저에서 서버로 이동한다.
->HTTPS 서버로 사용한다
XSS 위험
브라우저에 sessionStorage 특히 localStorage는 더욱 취약하며 악성스크립트로 인해 토큰의 정보를 빼갈 수 있다.
-> sessionStorage가 브라우저 탭이 닫히면 삭제되어 localStorage보다는 안전하지만 HttpOnly를 적용한 쿠키에 저장하는것이 가장 안전
- 토큰 만료 시에 별도의 로직 처리가 필요하다.
JWT와 세션을 합쳐 단점을 보완한 하이브리드 방식?
각각의 사용자 인증과 상태저장 방식은 장단점들이 있다.
세션은 서버에서 관리하기 때문에 안전하며 쿠키에서도 탈취 위험을 어느정도 방지할 수 있는 설정들이 있기때문에 보안상으로 안전하지만 서버에서 관리되는 데이터가 늘어나기때문에 메모리 또한 손실되며 관리가 복잡해지고 성능이 저하된다.
JWT는 상태를 서버가 저장하지않고 클라이언트에 두어 서버가 상태를 저장하지않고 전달받은 토큰을 통해 인증만 하면된다.
그러나 브라우저에서 서버로 이동되는 토큰은 탈취위험에 상당히 노출되어있으며 서버에서 클라이언트에 있는 토큰을 조작할 수 도없기에 보안 설정 또한 할수 없다.
그렇다면 둘을 합쳐서 한다면?
1. 로그인 시 토큰 발급
SessionID가 아닌 인증 정보를 담고있는 JWT토큰을 생성한다.
인증정보가 이미 다 포함되어져있기때문에 인증이 간편하며 서버에 세션이 저장되지않아 메모리 사용량을 낮춘다.
2. 토큰 저장
생성된 토큰을 클라이언트에 sessionStorage에 저장하는것이 아닌 Cookie에 저장한다.
Cookie에는 여러 보안을 위한 설정들을 서버에서 할 수있다.
따라서 토큰이 브라우저에서 서버로 이동 될때의 노출되는 위험 또한 쿠키안에 들어있다면 안전하게 이동할 수 있게된다.
장점
- 요청 시 정보가 이동하지 않기 때문에 토큰 탈취 위험이 적다.
- 토큰을 통해 인증을 간편히 할 수 있고 세션을 통해 강제 관리가 편리하고 서버에서도 토큰을 관리 할 수 있다.
단점
- 구현히 복잡해짐
- 서버가 완전한 무상태는 아니게 된다.
'Network' 카테고리의 다른 글
[Network] TCP/IP 4 계층을 기반으로한 웹 요청과 응답의 동작 흐름 (0) | 2025.07.07 |
---|---|
[Network] OSI 7계층의 역할과 목적 (0) | 2025.07.07 |
[Network] DNS의 역할과 동작 방식 (2) | 2025.07.07 |
[Network]URL과 도메인에 대해 알아보기 (0) | 2025.07.05 |
[Network]OSI 7 계층과 TCP/IP 4 계층의 차이점에 대해 알아보기 (1) | 2025.07.04 |