web/django

Django Cookie, Session, 그리고 JWT

민사민서 2024. 5. 20. 18:14

Authentication(인증)

- 사용자를 식별하는 프로세스 (누구인지 확인)

- 회원가입 과정, 로그인 과정

Authorization(인가)

- 인증된 사용자에게 특정 리소스나 기능에 접근할 수 있는 권한이 있는지 확인하는 프로세스

- 누구인지 확인이 완료된 사용자에게 '특정 작업 수행 권한'이 있는지 확인

- 권한이 필요한 요청 (게시글 수정, 게시글 삭제)

 

http 통신은 Connectionless (비연결성) + Stateless (무상태성) 을 가진다

어딘가에 유저 상태 정보를 저장할 필요가 있음 => Cookie, Session, Token

 

Cookie

- 사용자가 웹사이트를 방문하고 이용할 때 사용자의 브라우저에 저장되는 작은 정보 조각

- 공지 메세지 하루 안보기, 장바구니 담기 기능

- 사용자의 PC에 저장되기 때문에 접근 속도가 빠르고, 서버의 자원을 낭비하지 않아 효율적

- 보안 이슈

위 사진처럼 서버에서 발급한 쿠키는 헤더에 담겨서 클라이언트에게 보내짐

 

Session

- 쿠키에 직접 저장하기 민감한 정보들을 서버의 메모리나 데이터 베이스에 저장하고, 각각 누구의 것인지 구별
- 브라우저가 접속할 때 마다 쿠키와 세션의 조합으로 사이트 이용 가능

Session 기반 인증 방식

Session방식은 서버(의 세션 저장소)에 세션이라고 불리는 사용자의 정보를 저장

그리고 클라이언트에게는 Session ID를 발급, 클라이언트는 이 정보를 쿠키에 저장

이제 클라이언트는 매 요청마다 이 Session ID를 쿠키에 담아 함께 보내는데 ID가 일치하면 서버에서 사용자 인식+응답

 

장점은

1. 중요한 정보는 서버 세션에 존재하고 서버측에서 관리하기 때문에 클라이언트 변조에 영향을 받거나 데이터의 손상 우려가 없음 (세션 ID 탈취 감지 시 session 데이터 서버측에서 삭제하는 등의 조치 취하면 됨)
2. 세션 ID는 고유한 값이기 때문에 쿠키 값을 받았을 때 일일이 회원정보를 확인할 필요 없이 바로 어떤 회원인지를 확인할 수 있어 서버의 자원에 접근하기 용이함

 

단점은

1. 서버에 추가적인 저장공간이 필요함. 서버의 세션 저장소를 사용해 클라이언트의 상태를 모두 유지하고 있어야 하므로, 클라이언트 수에 따른 부하 up
2. 사용자가 많아지는 경우 서버를 확장해야하는데 이 때 세션의 관리 어려워짐

Cookie vs. Session

Cookie만 사용하는 것과 Session을 함께 사용하는 것의 차이는 중요한 정보(유저 상태 정보)의 저장 위치

- Cookie만 사용할 경우 중요한 정보의 내용까지 직접 그 안에 담아 주는 것

- Session을 함께 사용할 경우 Cookie에는 그 정보에 접근할 수 있는 키(세션 ID) 담아 준 다음 필요할 경우 그 키로 중요한 정보 (서버의 세션 저장소에 저장되어 있음)를 가져와서 꺼내주는 것

 

Token (JWT)

Session이 가지고 있는 단점(특히 서버 부하)을 극복하기 위해 등장

사용자의 인증 정보를 암호화한 일련의 문자열로 구성된 텍스트

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

JWT의 구조

  1. Header: 토큰의 유형(JWT), 서명 알고리즘(HS256)
  2. Payload: 토큰이 가지고 있는 정보 (그냥 서버에서 발급해주는 인증 정보)
  3. Signature: Header와 Payload를 하나의 비밀 키를 가지고 서명한 값 → “내(서버)가 발행했다!” (토큰 원산지 표기)
    • 비밀 키는 서버가 가지고 있기 때문에, 서버 아닌 다른 주체가 토큰을 생성하면 다른 키를 사용하게 되고 결국 다른 Signature 값이 나오게 됨
    • 마찬가지로 해커가 위조된 정보로 토큰의 Payload 값을 바꾸어도 JWT의 Signature값이 달라져 유효하지 않은 토큰임을 확인할 수 있음

Token(JWT) 기반 인증

사용자가 로그인 시, 서버는 토큰을 발급, 사용자는 발급된 토큰을 PC에 저장 (쿠키 등을 활용해 로컬에)

사용자가 다른 요청을 보낼 때 토큰을 헤더(요청의 한 영역)에 동봉해서 보냄

서버는 사용자의 토큰 정보를 검증하여(복호화 등) 인증한 뒤, 사용자의 권한을 확인하고 인가된 요청을 처리함

 

장점은

  1. 확장성이 뛰어남. JWT는 서버가 발급한 후 검증만 하기 때문에 추가 저장소가 필요하지 않고, 이는 서버를 확장하거나 유지, 보수하는데 유리함
  2. 간편함. Token 기반으로 하는 다른 인증 시스템에 쉽게 접근할 수 있음. Facebook, Google, Microsoft 로그인 등은 모두 토큰 기반으로 인증을 하는데, 권한을 받을 수도, 프로필을 써드파티 웹사이트에 제공하도록 허가할 수도 있음

단점은

  1. 이미 발급된 JWT에 대해서는 유효기간이 완료될 때 까지는 계속 사용이 가능함, Session 기반 인증은 쿠키가 악의적으로 이용될 경우 쿠키에 담긴 세션 ID를 가진 세션을 삭제하면 되지만 JWT는 불가능
  2. 이에 대한 해결책은 한 개의 토큰이 아닌 두 개의 토큰(Access Token, Refresh Token)을 사용하는 것
  3. Payload 정보가 제한적임, Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있음, 유저의 중요한 정보들은 Payload에 넣을 수 없음
  4. JWT는 Session ID보다 길기 때문에 정보가 많아질수록 네트워크에 부하 발생

Refresh Token + Access Token

- JWT에는 `Refresh Token`과 `Access Token`, 두 가지 종류가 있음

- 토큰의 보안을 위해 유효기간이 다른 두 개의 토큰을 사용하기
- 일반적으로 유효기간이 긴 Refresh Token유효기간이 짧은 Access Token을 발급하여, 인증에는 주로 유효기간이 짧은 Access Token을 사용함, 그리고 Access Token이 만료되면 Refresh Token을 통해 Access Token을 재발급
- Access Token은 유효기간이 짧기 때문에 탈취된다고 해도 실제 공격까지 이어질 가능성 down

사용자는 새로운 요청을 보낼 때마다 Access Token 함께 보내다가 Access Token이 만료되면 Refresh Token을 함께 서버에 보내 새로운 Access Token을 발급해달라고 요청 보냄

이때 서버는 Refresh Token이 유효한지 검사한 뒤, 유효하다면 Access Token을 재발급해주고 사용자는 이 Access Token을 가지고 이후에 새로운 요청들을 보내는 구조임~~