JWT는 JSON Web Token의 약자로, 웹에서 정보를 안전하게 전송하기 위한 인증 방식 중 하나이다.
이 방식은 두 개체 사이에서 JSON 객체를 사용하여 정보를 안전하게 전송하도록 설계되어 있다. 이 정보는 디지털 서명이 되어 있어서 보증할 수 있다. JWT는 클라이언트와 서버 간에 토큰 기반 인증을 할 때 주로 사용된다.
Cookie, Session, Token
- Cookie
로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일
사용자가 웹 사이트에 방문할 때 생성되며, 사용자의 PC에 저장된다.
쿠키의 주요 목적은 사용자의 이전 활동을 기억하고, 그 정보를 활용해서 사용자에게 맞춤화된 서비스를 제공하는 것이다.
1. 클라이언트가 서버에 요청을 보낸다.
2. 서버가 응답할 때, 클라이언트 측에 저장하고 싶은 데이터를 응답 헤더의 set-cookie에 담는다.
3. 이후 해당 클라이언트는 요청을 보낼 때마다 저장된 쿠키를 요청 헤더의 Cookie에 담아 보낸다. 서버는 쿠키에 담긴 정보를 바탕으로 해당 요청의 클라이언트가 누군지 식별하거나 정보를 바탕으로 추천 광고를 띄우거나 한다.
단점
1. 보안에 취약하다.
2. 용량 제한이 있어 많은 정보를 담을 수 없다.
3. 쿠키의 사이즈가 커질 수록 네트워크에 부하가 심해진다. - Session
서버 측에서 관리하는 사용자 정보
사용자가 웹 사이트에 접속하는 순간 생성되며, 사용자가 사이트를 종료하거나, 일정 시간 동안 반응이 없을 경우 세션은 종료된다.
세션은 쿠키를 이용해서 사용자를 식별하며, 사용자 별로 서버에 저장되어 있다.
1. 유저가 로그인을 하면 세션이 서버 혹은 DB에 저장된다. 이 때, 세션을 식별하기 위한 Session id를 기준으로 정보를 저장한다.
2. 서버에서 브라우저의 쿠키에 Session id를 저장한다.
3. 쿠키에 정보가 담겨있기 때문에 브라우저는 해당 사이트에 대한 모든 Request에 Session id를 쿠키에 담아 전송한다.
4. 서버는 클라이언트가 보낸 Session id와 서버 메모리로 관리하고 있는 Session id를 비교하여 인증을 수행한다.
단점
1. Session id 자체에는 유의미한 정보가 없지만 Session id를 탈취 당했을 경우 클라이언트인 것처럼 위장할 수 있다.
2. 서버에서 세션 저장소를 사용하므로 요청이 많아지면 서버에 부하가 심해진다. - Token
토큰은 인증이 필요한 사용자를 식별하기 위한 고유한 문자열
사용자가 로그인에 성공하면, 서버는 토큰을 발급하고 클라이언트는 이 토큰을 이용해서 추가 요청을 보낸다. 토큰 기반 인증에서는 쿠키나 세션과 달리 서버가 사용자 정보를 기억하고 있지 않아도 되므로, 서버의 부하를 줄일 수 있다. JWT(JSON Web Token)는 이러한 토큰 중 하나이다.
1. 사용자가 ID&PW로 로그인한다.
2. 서버 측에서 사용자에게 유일한 토큰을 발급한다.
3. 클라이언트는 서버 측에서 전달 받은 토큰을 쿠키나 스토리지에 저장해 두고, 서버에 요청을 할 때마다 해당 토큰을 HTTP 요청 헤더에 포함시켜 전달한다.
4. 서버는 전달받은 토큰을 검증하고 요청에 응답한다. 토큰에는 요청한 사람의 정보가 담겨있기에 서버는 DB를 조회하지 않고 누가 요청하는지 알 수 있다.
단점
1. 쿠키/세션과 다르게 토큰 자체의 데이터가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있다.
2. Payload 자체는 암호화 되지 않기 때문에 유저의 중요한 정보는 담을 수 없다.
3. 토큰을 탈취 당하면 대처하기 어렵다. (토큰의 유효기간을 설정하는 식으로 극복 가능)
JWT의 구성
HEADER.PAYLOAD.SIGNATURE의 형태
- Header
토큰의 타입(typ), 해싱 알고리즘(alg) 정보를 담고 있다. - Payload
클레임(Claims)이라 불리는 선언들을 포함하고 있다. 이는 사용자에 대한 정보나 다른 추가 정보를 담고 있다. - Signature
Header와 Payload를 인코딩한 후, 비밀키로 해싱하여 생성한다. (JWT를 안전하게 만들어주는 부분)
만약 비밀키가 노출되지 않았다면, 이 시그니처를 통해 JWT가 변조되지 않았음을 확인할 수 있다. -> 위변조 확인
JWT는 사용자의 세션을 서버에 저장하지 않기 때문에, 서버의 부하를 줄이면서도 안전하게 사용자 인증을 처리할 수 있는 장점이 있다. 그러나, 토큰 자체가 정보를 담고 있기 때문에 민감한 정보를 포함시키지 않아야 하며, 토큰을 탈취당하면 그 정보가 노출될 수 있다는 단점도 있다.
JWT를 이용한 인증 과정
- ID&PW로 로그인
- 서버가 클라이언트로부터 요청을 받으면, Header, Payload, Signature를 정의한다.
이들을 각각 Base64로 암호화 하여 JWT를 생성하고, 이를 쿠키에 담아 클라이언트에게 발급한다. - 클라이언트는 전달 받은 JWT를 로컬 스토리지에 저장한다. (쿠키나 다른 곳에 저장할 수도 있음)
API를 서버에 요청할때 Authorization header에 Access Token을 담아서 보낸다. - 클라이언트가 Header에 담아서 보낸 JWT가 내 서버에서 발행한 토큰인지 일치 여부를 확인하여 일치한다면 인증을 통과시킨다. 인증이 통과되었으므로 페이로드에 들어있는 유저의 정보들을 select해서 클라이언트에 돌려준다.
- 클라이언트가 서버에게 요청을 보냈는데 만약 액세스 토큰의 기한이 만료되었다면, 클라이언트는 리프레쉬 토큰을 이용해 서버로부터 새로운 액세스 토큰을 발급 받는다.
JWT은 서명(인증)이 목적이다.
JWT는 Base64로 암호화를 하기 때문에 디버거를 사용해서 인코딩된 JWT를 1초만에 복호화할 수 있다. 복호화 하면 사용자의 데이터를 담은 Payload 부분이 그대로 노출되어 버린다. 그래서 페이로드에는 비밀번호와 같은 민감한 정보는 넣지 말아야 한다.
토큰의 진짜 목적은 정보 보호가 아닌, 위조 방지이다.
참고 자료
'공부' 카테고리의 다른 글
ES5 문법 호환을 위한 Webpack, Babel 설치와 사용 (0) | 2024.03.12 |
---|---|
자바 웹 개발 워크북 (1-1~2) - 자바 웹 개발 환경 만들기 (0) | 2024.02.22 |
[Spring] MapStruct 사용하기 (ModelMapper -> mapstruct 변환) (0) | 2023.11.08 |
[Logging] @RestControllerAdvice를 이용한 에러 핸들링 (0) | 2023.11.05 |
[QueryDSL] Projections.bean과 fields의 차이 (0) | 2023.11.02 |