본문 바로가기

IT

JWT(JSON WEB TOKEN )

728x90

JWT : JSON WEB TOKEN 

토큰 : 특정 규칙에 맡게 문자열 

JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 JSON 토큰을 의미한다.

그리고 JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식이다

JWT는 JSON 데이터를 Base64 URL-safe Encode 를 통해 인코딩하여 직렬화한 것이며, 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명도 들어있다.

따라서 사용자가 JWT 를 서버로 전송하면 서버는 서명을 검증하는 과정을 거치게 되며 검증이 완료되면 요청한 응답을 돌려준다.

개요

브라우저와 SB(Spring Boot)가 통신할 때 최초 요청에는 쿠키에 대한 JSessionID가 없다. 새로운 사람이 왔네 하고 세션파일을 만들어주고 그 아이디를 쿠키에 실어준다. 스프링부트가 이 브라우저가 누군지 확인하는 것이 SessionID이다. 

 

(1세대) 

모바일과 통신할 때는 이것은 웹 브라우저가 아니다. 하지만 HTTP나 HTTPS와 맞게 요청만 하면 신경쓰지 않고 통신이 가능하다. 브라우저면 쿠키가 왔다갔다하지만 안드로이드나 IOS는 쿠키가 왔다갔다하게 할 순 있지만 잘 안한다. 그러다 보니까 세션을 못쓴다. 쿠키가 안되니까. 그러면 도대체 모바일은 어떻게 해야하나? 예전에는 ID나 PW를 기계안에 그대로 넣었고 매 요청마다 ID,PW를 같이 보냈다고 한다. 어쨌든 인증이 되지만 클라이언트에 ID, PW를 저장하고 매 요청마다 사용하는 것은 좋지 않았다.

 

(2세대)

사용자가 앱을 키면 ID,PW를 입력하고 로그인을 하면 ID, PW을 추가하여 서버와 통신하고 서버에 DB에 ID,PW에 저장된 회원을 찾고 APIKEY라는 유니크한 칼럼을 하나 만들어놓는데 이것을 클라이언트에 전달한다. 1세대와 큰 차이는 없지만 APIKEY를 사용한다. 보안측면에서는 더 낫다. APIKEY가 해킹당하면 재발급받으면 그만이다. 하지만 매 요청마다 DB에서 확인을 해야한다. 어떻게 하면 회원을 인증하는데 있어서 네트워크 DB통신 + SQL 처리까지 스킵하고 키를 받는 즉시 확인할 수 있을까 고민한다.

 

(3세대)

압축: zip + 비번 => 압축을 풀때 비밀번호가 필요하다. 이것을 이용해서 회원정보를 암호화 한 토큰을 APIKEY로 사용한다. DB없이 즉석에서 바로 사용이 가능하다. 맨 처음에 ID, PW를 맨 처음에 로그인하면 요청이 서버에 날라간다. 그러면 서버에서는 ID,PW을 가지고 DB에 처음 SQL을 날리고 존재한다 그러면 인증이 된 것이고 이 때 이 회원객체 로그인 정보를 json으로 바꾸고 이것을 암호화하고 비밀번호를 건다. 이 암호문 자체를 클라이언트에게 넘긴다. 이 키를 이제 토큰이라고 하자. 클라이언트는 이제 이 토큰을 가지고 서버에 요청을 하고 서버는 복호화한다. 서버는 DB에 접근없이 두번째 접근부터는 로그인 정보를  얻을 수 있다. CPU 연산만으로 인증이 가능하다. 

 

JWT Process

JWT Process

1. 사용자가 id와 password를 입력하여 로그인을 시도
2. 서버는 요청을 확인하고 secret key를 통해 Access token을 발급
3. JWT 토큰을 클라이언트에 전달
4. 클라이언트에서 API 을 요청할때  클라이언트가 Authorization header에 Access token을 담아서 보냄
5. 서버는 JWT Signature를 체크하고 Payload로부터 사용자 정보를 확인해 데이터를 반환합니다.
6. 클라이언트의 로그인 정보를 서버 메모리에 저장하지 않기 때문에 토큰기반 인증 메커니즘을 제공
인증이 필요한 경로에 접근할 때 서버 측은 Authorization 헤더에 유효한 JWT 또는 존재하는지 확인.
 

JWT 구조

 

JWT 구조

Header 에는 JWT 에서 사용할 타입과 해시 알고리즘의 종류가 담겨있으며, Payload 는 서버에서 첨부한 사용자 권한 정보와 데이터가 담겨있다. 마지막으로 Signature 에는 Header, Payload 를 Base64 URL-safe Encode 를 한 이후 Header 에 명시된 해시함수를 적용하고, 개인키(Private Key)로 서명한 전자서명이 담겨있다.

전자서명에는 비대칭 암호화 알고리즘을 사용하므로 암호화를 위한 키와 복호화를 위한 키가 다르다. 암호화(전자서명)에는 개인키를, 복호화(검증)에는 공개키를 사용한다.

JWT 장점

  • JWT 의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요없다.
  • 분산 마이크로 서비스 환경에서 중앙 집중식 인증 서버와 데이터베이스에 의존하지 않는 쉬운 인증 및 인가 방법을 제공
  • 토큰이 올바르게 서명되었는지 확인하는 것은 CPU 사이클을 필요로하며 IO 또는 네트워크 액세스가 필요하지 않으며 최신 웹 서버 하드웨어에서 확장하기가 간편하다.
  • URL  파라미터와 헤더로 사용
  • 수평 스케일이 용이
  • 디버깅 및 관리가 용이
  • 트래픽 대한 부담이 낮음
  • REST 서비스로 제공 가능
  • 내장된 만료
  • 독립적인 JWT

JWT 단점

  • 토큰은 클라이언트에 저장되어 데이터베이스에서 사용자 정보를 조작하더라도 토큰에 직접 적용할 수 없다.
  • 더 많은 필드가 추가되면 토큰이 커질 수 있습니다.
  • 비상태 애플리케이션에서 토큰은 거의 모든 요청에 대해 전송되므로 데이터 트래픽 크기에 영향을 미칠 수 있다.

**참고**

세션 방식은 스케일 아웃(서버를 늘릴 때)할 때 스티키세션이나 외부 세션저장소(Redis) 방식 중 하나를 도입해야 한다. 

여러 서버가 각 클라이언트의 대한 정보를 모두 가지고 있지 않기 때문에 매핑해주는 방법이 필요하다. 

JWT 방식은 스케일 아웃을 할 때 스티키세션이나 외부 세션저장소가 필요없다. 클라이언트(안드로이드, IOS, 리액트, 뷰, 앵귤러)와 통신할 때는 도메인이 다른 경우가 대다수이다. 그럴때는 세션이 아닌  JWT를 활용한다. JWT를 쓰면 로그인 정보는 클라이언트가 들고 있기 때문에 스케일 아웃과는 관련 없다. 대신 암호화 비밀번호는 공유해야한다.

 

출처 

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC#JWT_(JSON_Web_Token) 

http://www.opennaru.com/opennaru-blog/jwt-json-web-token/