sstaar_mx 2023. 7. 27. 01:13

 

최근 계속 통신과 관련된 내용에 대해서 다루고 있는 것 같은데,

개발을 오래 하진 않았지만, 이 통신 과정에서 발생하는 문제나 이슈가 가장 많았던 것 같아서

그냥 얼레벌레 개발을 하는 것 보다 확실하게 다시 내 생각으로 정리를 하는 것이 중요한 것 같아서 계속 정리를 진행해 보려 한다.

 


 

개념

 

이미지 출처 : https://star.ytn.co.kr/_sn/1406_202110232003021057

 

🙋🏻‍♂️ : JWT? 그 최근에 놀면뭐하니에서 하던거 아닌가?
??? : 하... (진심으로 이렇게 얘기한 사람 있을듯.. 암튼 아님.. 진짜 아님)

 

JWT는 Json Web Token의 약자로 클라이언트와 서버간의 정보를 전달할 때 사용하는 인증 방식이다.

보통 통신을 하게 되면 클라이언트의 요청에 의해 서버에 데이터를 전달해 주는 형태로 진행이 되는데

서버 입장에서는 이 클라이언트가 인증된 유저인지를 확인하는 것이 중요하다.

 

클라이언트의 데이터 요청이 단순한 데이터를 요청하는 경우도 있겠지만유저의 민감한 정보가 담긴 데이터를 요청하게 되는 경우도 발생할 수 있어서,신뢰할 수 있는 요청인지에 대한 확인이 이루어져야 하는데 이 JWT는 안전하게 인증을 할 수 있게 하는 방식이다.

 

🙋🏻‍♂️ : 그럼 JWT만 알면 되겠다! 개꿀?

 

물론 JWT 말고 인증과 관련된 다른 방식들이 존재한다.

 


 

쿠키 & 세션

 

* 쿠키 / 세션에 대한 내용은 아래 [레퍼런스]에 있는 인파님의 글을 보고 참고했습니다.
* 해당 개념에 대해서 제가 이해하기 위해 추가로 작성한 글도 있으니 내용에 참고하시기 바랍니다.
* 각 개념에 대한 자세한 내용은 아래 인파님의 글을 참고해주세요!

 

우선 쿠키에 대해서 알아보자. 쿠키는 key-value 형식으로 이루어진 문자열이다.

이 쿠키는 클라이언트가 웹사이트에 접속할 때 응답으로 서버에서 브라우저에 설치를 하는 작은 기록 정보 파일이다.

웹사이트를 접속하자마자 담긴 쿠키는 클라이언트가 서버에 요청을 보낼때 마다 쿠키를 헤더에 담아 서버에 보내게 된다.

그래서 서버는 이 쿠키를 바탕으로 클라이언트가 누구인지 식별하는 방식으로 클라이언트를 인증하게 된다.

 

출처 : 프리미어리그 메인 페이지 (https://www.premierleague.com/)

 

내가 자주 접속하는 프리미어리그 페이지에도 웹사이트에 접속하자마자 이러한 알림창을 띄워준다.

내용을 요약하면 쿠키를 통해서 우리 웹사이트가 좀 더 클라이언트 경험에 도움을 줄 수 있게 하기 위해,

쿠키를 허용하는 것을 요청하는 내용이다.

 

🙋🏻‍♂️ : 아니 아까는 접속하자마자 클라이언트 브라우저에 심는다면서요?

 

아마도 이렇게 요청 메세지를 보내는 것은 쿠키가 가지고 있는 단점이 몇가지 있기 때문이지 않을까 싶다.

작은 기록 정보 파일이기 때문에, 쿠키에는 용량 제한이 있다는 점도 있고,

브라우저마다 쿠키에 대한 지원 형태가 달라 브라우저간 공유가 불가능하다는 점도 있지만

가장 큰 단점은 쿠키를 요청하게 되면 쿠키의 값을 그대로 보내기 때문에 유출 및 조작 당할 위험이 있어 보안상 취약하다는 부분이 있다.

아무래도 이러한 부분 때문에 쿠키를 허용할지에 대한 요청을 하는것을 묻는것이 아닐까 싶다.

 


 

세션은 이런 쿠키의 보안적인 이슈로 클라이언트의 민감한 정보를 서버에서 관리하는 방식이다.

유저가 어떤 웹사이트에 로그인을 하게 되면 해당 정보를 특정하는 세션 ID가 서버에 저장되고, 해당 ID를 브라우저 쿠키에 담는다.

클라이언트는 받아온 쿠키를 저장하고, 서버에 대한 요청을 할 때 해당 쿠키를 요청에 담아 전달하게 된다.

서버에서는 이 요청안에 있는 쿠키와 서버의 세션 ID를 비교하는 방식으로 클라이언트를 인증하게 된다.

 

이 방법은 모든 정보를 그대로 저장하는 쿠키와는 달리 세션 ID의 값만 담고 있기에 보안상 쿠키보다 효과적일 수 있지만

세션 ID 자체를 탈취 한 뒤, 해당 ID를 이용해 클라이언트인 척 위장할 수 있다는 한계가 있다.

그리고 서버에서 이러한 데이터를 관리하다 보니 요청이 많아지면 서버에 부하가 심해질 수 있다는 단점이 있다.

 


 

토큰 방식 (근데 JWT를 곁들인..?)

 

토큰 방식은 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트가 인증 되었다는 의미로 토큰을 발급해 부여한다.

토큰을 발급받은 클라이언트는 서버에 다른 요청을 할 때 헤더에 이 토큰을 담아서 보내게 되고,

서버는 클라이언트에서 받은 토큰을 서버에 토큰과 비교해 인증 과정을 처리하게 된다.

 

🙋🏻‍♂️ : 아니 이러면 세션 방식이랑 비슷한거 아닌가요?

 

세션 방식은 클라이언트에서 요청을 받으면 클라이언트의 상태를 계속해서 서버에서 유지해 놓고 사용을 하게 된다.

그러나 토큰 방식은 발급을 한 뒤 상태를 서버에서 유지하지 않는 Stateless 한 상태로 진행이 된다.

이러한 방식을 통해 서버의 부하를 줄여주는 특징을 가지고 있다.

 

여기서 JWT는 이 토큰 방식 중의 하나로 인증에 필요한 정보들을 암호화 시킨 JSON 형태의 토큰이다.

이 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명도 들어가 있다.

 

 

JWT의 구조

 

출처 : 숨고 블로그 (https://blog.soomgo.com/blog/jwt-for-all/)

 

JWT는 3가지 구성 요소(Header, Payload, Signature)로 이루어져 있고, 각 구성 요소들은 dot(.)으로 구분이 되어 있다.

 

우선 Header는 JWT의 첫번째 구성 요소고, 일반적으로 2가지 정보를 담고 있다.

아래는 디코딩 된 Header에 대한 예시 구조다.

// Header 예시

{
    "alg" : "HS256", // Signature을 만드는데 사용한 알고리즘 정보
    "typ" : "JWT"    // Token의 타입
}

 

두번째 Payload에는 실질적으로 전달해야하는 정보인 클레임 (Claim)이 담겨있다.

이 클레임에는 크게 3가지 종류로 나눠진다.

 

1. Registered Claims (등록된 클레임)

  - 등록된 클레임은 이미 JWT 표준으로 지정된 클레임이다. 총 7가지의 Registered Claim이 존재하며,

     해당 클레임을 무조건 전부 사용해야 되는 것은 아니고 적절히 상황게 맞게 사용하면 된다.

  - iss: 토큰 발급자  /  sub: 토큰 제목  /  aud: 토큰 대상자  /  exp: 토큰 만료시간

     iat: 토큰 발급 시간  /  nbf: 토큰 활성화 시간  /  jti: JWT의 고유 식별자

 

2. Public Claims (공개 클레임)

  -  개발자들이 직접 정의해서 사용할 수 있는 클레임이다. 이 클레임은 기존에 등록 된 클레임과 충돌을 방지하기 위한 규칙을 따라야 한다.

 

3. Private Claims (비공개 클레임)

  -  이 클레임은 오직 사용자와 서버 사이에서만 합의해서 사용하는 클레임이다.

// Payload 예시

{
    "exp": "1245678900", //Registered Claims
    "https://velopert.com/jwt_claims/is_admin": true, //Public Claims
    "user_id" : 12345123 //Private Claims
}

 

마지막 Signature는 헤더와 페이로드를 암호화해 생성된 서명이다.

시그니처는 헤더의 인코딩된 내용과 페이로드의 인코딩된 내용을 더한 뒤, Secret Key와 알고리즘을 이용하여 암호화를 한다.

여기서 헤더와 페이로드는 단순 인코딩을 한 값이기 때문에, 누군가가 디코딩을 통해 조작을 변형을 할 수 있지만,

Secret Key는 서버에서 관리하는 값이기 때문에, 유출이 되지 않는 이상 디코딩을 할 수 없다.

그래서 이 시그니처는 토큰의 위조나 변조를 확인하기 위해 사용이 된다.

 


JWT의 장점과 단점

 

완벽해 보이는 JWT에도 장점과 단점이 존재한다.

 

우선 장점을 살펴보면 위에서 언급했던 특징들이 곧 장점이다.

토큰 자체에 정보를 포함하고 있어서 서버가 계속 상태를 유지하지 않아도 되고,

시그니처를 통해 토큰의 변조를 방지할 수 있다는 장점이 있다.

그리고 쿠키와는 다르게 다양한 시스템에 접근 및 권한 공유가 가능하다는 장점도 있다.

 

그러나 이 방식의 단점도 물론 존재한다.

먼저 토큰 자체에 정보가 있다는 점이 장점이자 단점이 될 수 있다.

암호화를 하긴 하지만 완벽하다고는 할 수 없기 때문에, 민감한 정보가 토큰에 들어가서는 안된다.

또한 토큰에 담는 정보가 많아질 수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.

 


 

레퍼런스

 

- 인파님 블로그 글 [ 이동 ]

- 숨고 블로그 글 [ 이동 ]