지금까지는 세션을 이용해 로그인을 구현했다. 이제는 세션을 이용하지 않고 stateless한 방식으로 로그인을 구현해보도록 하자.
JWT(Json Web Token)
JWT는 Stateless 상태를 유지하며, 서버에서 사용자를 식별할 수 있는 수단을 제공한다. 과정은 다음과 같다.
- 사용자가 인증 요청을 보낸다.(로그인)
- 서버에서 사용자가 성공적으로 인증되면 JWT를 반환한다.
- 클라이언트는 JWT를 로컬 영역에 저장하고, 이후 서버에 요청을 보낼 때 JWT를 HTTP 헤더에 포함시킨다.
- 서버는 클라이언트가 전달한 JWT를 통해 사용자를 식별하며 요청을 어떻게 처리할지 결정한다.
JWT vs Session
- Stateful vs Stateless
- Stateful 아키텍처의 장단점
- 일단 Session을 사용하고 있으면, Stateful 하다고 할 수 있다.
- 앞서 살펴본 것처럼 수평확장(Scale-Out) 과정이 쉽지 않다.(Session Cluster가 반드시 필요)
- Session Cluster의 장애 또는 성능 병목이 서비스 전체에 큰 영향을 줄수 있다.
- 단일 사용자의 다중 로그인 컨트롤, 사용자 유효성 체크, 강제 로그아웃 기능 구현이 쉽다.
- Stateless 아키텍처의 장단점
- Session을 전혀 사용하지 않아야한다.(HTTP 프로토콜 자체가 Stateless)
- 수평확장이 매우 쉽다.(Session Cluster가 필요 없음)
- 단일 사용자의 다중 로그인 컨트롤, 사용자 유효성 체크, 강제 로그아웃 기능 구현이 어려다.
- 무엇보다 완전한 Stateless 아키텍처 기반으로는 서비스 개발이 어렵다.
- 완전한 Stateless 서비스는 정적 리소스(html, css, javascript, 이미지 등)를 서비스 하는데 적합함 — 예: AWS S3
- 서버는 어떤식으로는 사용자를 식별할 수 있어야 함 (단, Session 사용 금지)
- Stateful 아키텍처의 장단점
JWT 구조
- Header, Payload, Signature 세 부분으로 구성된다.
- Header, Payload, Signature 세 부분을 Base64 Url-Safe 방식으로 인코딩하고 dot(.)을 구분자로 결합한다.
Header
- JWT를 검증하는데 필요한 정보를 담고 있다. (토큰 타입, 사용된 알고리즘)
- 알고리즘은 HMAC, RSA 방식을 지원한다.
- HMAC 알고리즘에서 비밀키는 최소한 알고리즘의 서명 길이만큼의 비트를 가지고 있어야한다. (HS512 — 64byte)
Payload
- JWT를 통해 전달하고자 하는 데이터(Claim-Set)
- Claim 자체는 쉽게 말해 Key-Value 데이터 쌍을 의미한다.
- JWT 자체는 암호화되는 것이 아니기 때문에 민감정보를 포함해서는 안됨
- Reserved Claims, Public Claims, Custom Claims 으로 구분됨
- Reserved Claims — 미리 등록된 Claims 필수적으로 사용할 필요는 없지만 사용을 권고한다.
- iss — 토큰을 발급한 발급자 (Issuer)
- exp — 만료시간이 지난 토큰은 사용불가
- nbf — Not Before의 의미로 해당 시간 이전에는 토큰 사용불가
- iat — 토큰이 발급된 시각
- jti — JWT ID로 토큰에 대한 식별자
- Public Claims — 사용자 마음대로 쓸 수 있으나 충돌 방지를 위해 미리 정의된 이름으로 사용을 권고한다.
- Custom Claims — 사용자 정의 Claims (Reserved, Public 에 정의된 이름과 중복되지 않도록함)
- Claim 자체는 쉽게 말해 Key-Value 데이터 쌍을 의미한다.
Signature
- 토큰 생성 주체만 알고 있는 비밀키를 이용해 헤더에 정의된 알고리즘으로 서명된 값
- 토큰이 위변조 되지 않았음을 증명함
'Spring > Security' 카테고리의 다른 글
Spring Security 11: JWT #2 (0) | 2023.08.14 |
---|---|
Spring Security 9: Spring Session (0) | 2023.08.12 |
Spring Security 8: 데이터베이스를 이용해 인증하기(JPA) #2 (0) | 2023.08.12 |
Spring Security 7: 데이터베이스를 이용해 인증하기(JDBC) #1 (0) | 2023.08.11 |
Spring Security 6: Thread Local (0) | 2023.08.11 |