Jwt 세션방식을 토큰 방식으로..
JWT란?
Json Web Token의 약어이며 Json 포맷으로 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다. 주로 회원 인증이나 정보 전달에 사용된다. 기존에 사용되던 Session에서 jwt로 많이 넘오는 이유는 크게 2가지 측면이 있다.
1. 서버의 부하
session에 저장한다는 것은 결국 서버의 저장공간을 사용하게 되므로 많은 이용자가 사용되는 어플일 경우 그만큼의 부하가 생기는 것이며 HTML5부터는 브라우저에 5MB의 저장공간을 쓸 수 있는 스토리지도 생겼기에 이를 이용한 것
2. 서버간 세션 동기화 문제
트래픽이 몰리게 될 경우 컴퓨팅 파워를 높여서 해결 하는 방법보단 서버를 늘려서 부하분산을 하는 경우가 더 많다. 이 경우 특정 서버에만 저장된 세션의 정보를 다른 서버에서 사용할 경우 동기화 문제가 생긴다. 동기화 해주는 설정을 추가로 하거나 Session DB를 만들어서 관리 해야한다.
내가 직접 해본건 아니지만 듣기로는 동기화 해주는 설정은 구현하기가 까다롭고 어렵다 들었고, DB의 경우 하루에도 수많은 이용자가 로그인/로그아웃을 하는데 이를 DB로 관리하는건 굉장히 비효율적이라 생각이 든다.
그래서 클라이언트가 인증정보(토큰)를 갖고 있고 서버에 요청할 때 토큰을 함께 보내어 서버에서는 그 토큰이 유효한지 판단하여 처리를 하기 때문에 서버가 세션에 회원들 정보를 항상 들고 있을 필요가 없어서 부하를 줄일 수 있다.
JWT 구성
JWT는 세 파트로 나눠지며 각 파트는 점으로 구분하여 xxxx.yyyyy.zzzz 이런식으로 표현됩니다. 순서대로 헤더, 페이로드, 서명으로 구성됩니다. Josn 형태인 각 부분은 Base64로 인코딩되어 표현합니다.
1. 헤더
토큰의 헤더는 typ과 alg 두 가지 정보로 구성됩니다. alg는 헤더를 암호화 하는 것이 아니고 Signature를 해싱하기 위한 알고리즘을 지정하는 것이다. typ: 토큰의 타입을 지정 ex)JWT, alg: 알고리즘 방식을 지정하며, 서명 및 토큰 검증에 사용
2. 페이로드
토큰의 페이로드에는 토큰에서 사용할 정보의 조각들인 클레임이 담겨 있다. 클레임은 총 3가지로 나누어지며 Key/Value 형태로 다수의 정보를 넣을 수 있다.
- iss : 토큰 발급자
- sub : 토큰 제목
- aud : 토큰 대상자
- exp : 토큰 만료 시간
- nbf : 토큰 활성 날짜
- iat : 토큰 발급 시간
- jti : JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token)등에 사용
3. 서명
서명은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다. 서명은 위에서 만든 헤더와 페이로드의 값을 각각 Base64로 인코딩하고, 인코딩한 값을 비밀키를 이용해 헤더에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 Base64로 인코딩하여 생성한다.
JWT Process
1. 사용자가 id와 password를 통해 로그인을 시도합니다.
2. 서버는 요청을 확인하고 시크릿 키를 통해 액세스 토큰을 생성후 클라이언트에게 전달
3. 클라이언트는 토큰을 브라우저에 저장, 이후 API을 요청할 때 Header에 Access token을 담아서 서버로 보냅니다.
4. 서버는 토큰의 유효성을 검사하고 유저의 정보와 권한을 확인 후 서비스 제공
주의할점
-페이로드 자체는 암호화 된 것이 아니라 base64로 인코딩된 것이다. 중간에 payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로 토큰에 중요 데이터는 넣지 않아야 한다.
-JWT는 한번 만들어지면 제어가 불가능하다. 즉 토큰을 임의로 삭제가 불가능하니 꼭 만료시간을 넣어줘야함
-정보가 많아질수록 토큰의 길이가 늘어가 네트워크에 부하를 줄 수 있다.