JWT 기본
기존 Session 처리방식
이전에 JWT를 사용하지 않았다면 사용자의 로그인 정보는 Session을 이용하여 처리했을 것이다.
Spring Security를 통해 로그인 된 사용자의 정보를 가져온다던지, session.getAttribute("로그인한 유저 정보");
를 가져온다면 session을 이용하는 것이다.
세션을 이용한다면 로그인 한 사용자 정보는 WAS의 세션 저장소에 저장된다.
그렇기 때문에 로그인한 사용자 수가 많을수록, 저장하는 정보가 많을수록 WAS에는 무리가 간다.
문제는 이 뿐만이 아니다.
사용자 정보가 WAS에 귀속되어있기 때문에 WAS가 다중화 되어있고, L4장비 등의 로드밸런싱이 Round Robin과 같은 방식이라면
페이지 동작 중 로그인이 끊기는 문제가 발생한다. (사실 이는 세션클러스터링 방법으로 해결이 가능하다.)
- 세션 기반 데이터 처리
- 클라이언트가 브라우저 쿠키에서 확인할 수 있는 Tomcat에서 생성해준 JSESSION 데이터
JWT 를 사용한 처리 방식
JWT는 Json Web Token 의 약자로 말 그대로 JSON 형태의 Web Token이다.
https://jwt.io/ 에서 토큰을 디코딩, 검증 해볼 수 있으며 아래와 같이 token 내용은 3개로 구분된것을 확인 할 수 있다.
좌측은 실제 jwt 이고, 우측은 디코딩 된 내용인데 좌측의 jwt가 ‘.’을 기준으로 총 3구역으로 나뉘어있는걸 볼 수 있다.
헤더에는 JWT의 변조등을 확인하기 위한 암호화 알고리즘의 정보가 들어가며, 본문에는 실제 JWT에 담고자하는 사용자 정보를 담을 수 있다.
맨 아래 서명은 헤더와 본문을 합친 문자열을 정의한 알고리즘과 비밀키를 이용하여 생성한 값으로 JWT를 복호화 하는 과정에서 데이터가 변조되었는지 비교할때 사용된다.
-
JWT기반 처리 방식
생성된 JWT를 쿠키에 담을지, 세션에 담을지, localstorage에 담을지는 많은 관점이 존재한다. 편의상 쿠키에 담는것으로 작성된 다이어그램 -
클라이언트가 브라우저 쿠키에서 확인할 수 있는 JWT 데이터
이때 JWT 내용은 base64 인코딩만 적용되어있어 쿠키에서 조회되는 value를 그대로 디코딩하면 내용이 노출된다.
그러므로 민감한정보 (개인정보, 비밀번호 등) 는 jwt에 포함되면 안된다.
JWT를 사용하여 데이터를 쿠키에 저장함으로써
- 사용자 정보를 WAS 저장소에 담지 않고 클라이언트 쿠키/로컬스토리지 에 저장하기 때문에 로그인한 사용자가 많아져도 WAS는 부담이 적다.
- WAS가 다중화 되어있어도 사용자 정보는 클라이언트 쿠키에서 가져오기 때문에 로드밸런싱 방식 또는 오토스케일링의 영향을 받지 않는다.
그러나 세션과 달리 클라이언트 로컬에 저장되며 통신 시 함께 전송되기 때문에
- 저장 혹은 전달 시의 보안에 신경 써야 하며 탈취 되었을때를 대비하여 민감한 정보를 저장하지 않는다.
- 매 요청마다 JWT을 변조 여부 확인, payload 데이터 변환 작업을 거쳐야한다. (Filter 또는 Spring Security를 이용)
- JWT는 생성 시 만료시간을 정하여 클라이언트에게 전달하기 때문에 서버에서 토큰을 만료시킬 수 있는 방법이 없다. (Refresh Token과 같은 대안 필요)