5. JWT란 무엇일까?
JWT란?
JWT(Json Web Token)란 JSON 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 WebToken 이다.
즉, 토큰의 한 종류라고 생각하면 된다.
일반적으로 쿠키 저장소를 사용하여 JWT를 저장한다.
JWT 사용 이유
1. 서버가 1대인 경우
Session1이 모든 Client의 로그인 정보를 소유하고 있다.
나의 궁금증
Session1이 모든 Client의 로그인 정보를 가지고 있다면 서버는 각 Client를 어떻게 구분하는가?
Session1을 서버에 보내서 Client 정보를 파악하는걸로 알고있는데 모두 같은 Session이면 구분이 가능한건가?
2. 서버가 2대 이상인 경우
서버의 대용량 트래픽 처리를 위해 서버 2대 이상 운영이 필요할 수 있다.
Session마다 다른 Client 로그인 정보를 가지고 있을 수 있다.
Session1 : Client1, Client2, Client3
Session2 : Client4
Session3 : Client5, Client6
만약 Client1의 로그인 정보를 가지고 있지 않은 Server2나 Server3에 API 요청을 하게되면 문제가 발생하지 않을까?
해결방법
1) Sticky Session : Client마다 요청 Server를 고정한다.
2) 세션 저장소를 생성하여 모든 세션을 저장한다.
3. 세션 저장소 생성
Session storage가 모든 Client의 로그인 정보를 소유하고 있기 때문에 모든 서버에서 모든 Client의 API 요청을 처리할 수 있다.
4. JWT 사용
로그인 정보를 Server에 저장하지 않고, Client에 로그인 정보를 JWT로 암호화하여 저장 -> JWT 통해 인증/인가
모든 서버에서 동일한 Secret Key를 소유한다.
Secret Key를 통한 암호화 / 위조 검증(복호화 시)
JWT 장/단점
1. 장점
동시 접속자가 많을 때 서버 측 부하 낮춤
Client, Server가 다른 도메인을 사용할 때
예) 카카오 OAuth2 로그인 시 JWT Token 사용
2. 단점
구현의 복잡도 증가
JWT에 담는 내용이 커질수록 네트워크 비용 증가 (클라이언트->서버)
생성된 JWT를 일부만 만료시킬 방법이 없음
Secret key 유출 시 JWT 조작 가능
JWT 사용 흐름
1. Client가 username, password로 로그인 성공 시
서버에서 "로그인 정보" -> JWT로 암호화 (Secret Key 사용)
Sample
서버에서 직접 쿠키를 생성해 JWT를 담아 Client 응답에 전달
JWT 전달방법은 개발자가 정함
응답 Header에 아래 형태로 JWT 전달
Cookie cookie = new Cookie(AUTHORIZATION_HEADER, token); // Name-Value
cookie.setPath("/");
// Response 객체에 Cookie 추가
res.addCookie(cookie);
브라우저 쿠키 저장소에 자동으로 JWT 저장됨
2. Client 에서 JWT 통해 인증방법
서버에서 API 요청 시마다 쿠키에 포함된 JWT를 찾아서 사용
쿠키를 찾는 코드
쿠키에 담긴 정보가 여러 개일 수 있기 때문에 그 중 이름이 JWT가 담긴 쿠키의 이름과 동일한지 확인하여 JWT를 가져온다.
Server
Client가 전달한 JWT 위조 여부 검증(Secret Key 사용)
JWT 유효기간이 지나지 않았은지 검증
검증 성공 시,
JWT 에서 사용자 정보를 가져와 확인
ex) GET /api/products : JWT 보낸 사용자의 관심상품 목록 조회
JWT 구조
JWT는 누구나 평문으로 복호화 가능하다.
하지만 Secret Key가 없으면 JWT 수정 불가능하다.
결국 JWT는 Read only 데이터이다.
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
1. Header
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
{
"sub": "1234567890",
"username": "카즈하",
"admin": true
}
3. Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Payload에 실제 유저의 정보가 들어있고, HEADER와 VERIFY SIGNATURE 부분은 암호화와 관련된 정보 양식이라고 생각하면 된다.