[JWT] JWT와 JWT를 사용하는 이유

u-nij·2022년 10월 14일
5

JWT 구현하기

목록 보기
1/8
post-thumbnail

JWT(Json Web Token)

JWT는 유저를 인증하고 식별하기 위한 토큰(Token) 기반 인증이다. 토큰 자체에 사용자의 권한 정보나 서비스를 사용하기 위한 정보가 포함된다. JWT를 사용하면 RESTful과 같은 무상태(Stateless)인 환경에서 사용자 데이터를 주고받을 수 있게 된다. 세션(Session)을 사용하게 될 경우에는 쿠키 등을 통해 사용자를 식별하고 서버에 세션을 저장했지만, JWT와 같은 토큰을 클라이언트에 저장하고 요청시 HTTP 헤더에 토큰을 첨부하는 것만으로도 단순하게 데이터를 요청하고 응답을 받아올 수 있다.

구조

JWT는 Header, Payload, Signature로 구성된다. 각 요소는 .으로 구분된다.

JWT에서 사용할 타입(typ)과 해시 알고리즘(alg)의 종류가 담겨있다.

{
  "typ": "JWT",
  "alg": "HS512"
}

Payload

서버에서 첨부한 사용자 권한 정보와 데이터인 클레임(Claim) 담겨있다. 클레임은 Key/Value 형태로 된 값을 가진다. 저장되는 정보에 따라 Registered Claims, Public Claims, Private Cliams로 구분된다.

등록된 클레임(Registered Claims)
iss: 토큰 발급자(issuer)
sub: 토큰 제목(subject)
aud: 토큰 대상자(audience)
exp: 토큰 만료 시간(expiration)
nbf: 토큰 활성 날짜(not before), 이 날이 지나기 전의 토큰은 활성화되지 않는다.
iat: 토큰 발급 시간(issued at)
jti: JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용한다.

{
  "sub": "subject",
  "iss": "abc",
}

공개 클레임(Public Claims)
공개 클레임들은 충돌이 방지된 이름을 가지고 있어야한다. 주로 URI 형식으로 짓는다.

{
  "https://velog.io/jwt/public": true
}

비공개 클레임(Private Cliams)
클라이언트와 서버 협의하에 사용되는 클레임이다. 공개 클레임과는 달리 이름이 중복되어 충돌될 수 있기 때문에 유의해야 한다.

{
  "username": "kim"
}

Signature

Header, Payload를 Base64 URL-safe Encode 한 이후, Header에 명시된 해시함수를 적용하고, 개인키(Private key)로 서명한 전자서명이 담겨있다. 이는 Header, Payload가 변조되었는지 확인하기 위해 사용되는 중요 정보이며, JWT를 신뢰할 수 있는 토큰으로 사용할 수 있는 근거가 된다.

Base64 URL-safe Encode
웹으로 전송하기 위해 사용하는 문자가 Base64 형태의 문자이다. 일반적인 Base64 Encode 에서 URL 에서 오류없이 사용하도록 '+', '/' 를 각각 '-', '_' 로 표현한 것이다.

세션(Session)

사용자가 어떤 서버에 로그인을 하기 위해 ID를 입력했다고 가정했을 때, 서버는 입력받은 ID에 대한 "인증" 단계를 거치고, 서버 안의 세션 저장소에 해당 내용을 담은 세션을 저장한다. 이 저장된 것을 "세션ID"라고 한다.서버는 저장된 세션ID를 HTTP Response의 Cookie 값에 세팅해 사용자에게 보내게 된다. 이후에 사용자는 권한이 필요한 요청을 서버에 보낼 때 세션ID를 보내게 되고, 서버는 해당 세션ID가 세션 저장소에 있는지 확인하고 "인가"의 여부를 결정헌다.
예를 든다면, 서버가 세션을 사용할 때, 사용자는 로그인 상태를 유지하기 위해 세션ID를 쿠키 값으로 가지고 있어야 한다. 만약 로그인한 상태에서 쿠키 초기화를 하게 된다면, 로그인 상태를 유지하게 해주던 세션ID를 초기화한 것이 되기 떄문에 다시 로그인을 해야한다.

인증(Authentication): 접근자가 누구인지 확인하는 절차
인가(Authorization): 인증을 마친 접근자에게 권한을 허락하는 절차

세션의 문제점

이러한 세션 방식은 여러 대의 서버를 사용하게 될 때 문제가 발생한다. 세션 저장소는 로드 밸런싱을 했을 때 공유되지 않는다. 인가 절차를 거칠 때, 다른 서버로 접근하게 되면 인가가 불가능하게 된다.
즉, 1번 서버에서 발급된 세션ID를 가지고 2번 서버에서 인가 과정을 시도하는 것이 불가능하다. DB를 사용해서 해결이 가능하겠지만, 접근하는 것 자체에서 네트워크와 하드 디스크 IO 비용이 발생한다는 문제가 있다.

JWT와 세션의 차이점

JWT 토큰과 세션의 가장 큰 차이점은 "인가"에 대한 정보를 누가 담고 있냐이다. 세션은 서버의 세션 저장소에 해당 인증 내용을 담지만, JWT 토큰은 토큰 안에 인증 내용을 담고 있다. 사용자가 요청을 했을 때 토큰만 확인하면 되므로 세션 관리가 필요 없어진다. 따라서, JWT 토큰을 활용하면 각각 로드 밸런싱된 서버에 토큰 검증 클래스나 메소드만 있다면 인가 과정을 해결할 수 있다.

참고

https://pronist.dev/143
https://velog.io/@jjy5349/%EC%84%B8%EC%85%98%EA%B3%BC-JWT-%ED%86%A0%ED%81%B0-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-2%ED%8E%B8
https://koonsland.tistory.com/57

0개의 댓글