관리 메뉴

제뉴어리의 모든것

[Section 4] [Spring Security] JWT 인증 - 1 본문

코드스테이츠/정리 블로깅

[Section 4] [Spring Security] JWT 인증 - 1

제뉴어리맨 2022. 9. 26. 15:55

전체 항목

  • 자격증명 방법의 종류와 설명
  • JWT란
  • JWT 실제 적용 

 

자격증명 방법의 종류  설명

자격증명이 왜 필요할까?
HTTP 통신의 특성인 비연결성(Connectionless), 비상태성(Stateless) 때문이다.
- 비연결성 : 서버와 클라이언트의 연결은 한번의 request, response로 끊킨다.
- 비상태성 : 연결 대상의 대한 상태를 가지고 있지 않는다.

그로 인해, 자격을 검증할 수 있는 다양한 방법이 있는데 그 중 세션 방식과 토큰 방식을 보겠다.


- 세션 방식
클라이언트가 로그인 요청을 하고 서버에서 해당 요청에 대해 검증을하여 인증을 한 뒤,
해당 요청을 한 클라이언트만을 위한 ID를 만들어 준다. 그리고 그 ID와 클라이언트의 정보를 담아 "Session" 이란것을 만들어서 서버가 관리하는 DB (인메모리DB 일수도, 기타 다른 DB일 수도 있다) 에 세션 정보를 저장한다.
그리고 클라이언트에게는 response시 세션 ID를 "Cookie"로써 내려주고, 클라이언트는 다음부터 어떤 request던지 세션ID를 "Cookie"로써 헤더에 포함하여 서버에 전송한다.
그로인해 서버는 해당 요청이 로그인된 클라이언트의 요청임을 인지

참조 : https://januaryman.tistory.com/477

 

[SEB BE] [Section 4] [인증/보안] 기초

전체 내용 목차 HTTPS Hashing Cookie Session JWT 웹 보안 공격에 대하여 HTTPS Hyper Text Transfer Protocol Secure Socket layer 의 약자. 또는 HTTP over SSL(TLS), HTTP over Secure. HTTP에 비해 보안이 강..

januaryman.tistory.com

- 세션 기반의 특징
1. 세션 정보는 서버의 저장소에서 관리

2. 클라이언트도 세션 ID를 Cookie로써 가지고 있음

3. 클라이언트는 request시 세션 ID만 같이 보내면 되므로 네트워크 트래픽이 상대적 적음.

4. 유저 정보를 담고 관리할 수 있는 정보인 세션을 서버에서 관리하므로 보안측면에서 상대적으로 안정

5. 서버 확장시 "세션 불일치 문제" 발생 가능함

6. 현재 로그인 상태의 유저가 많을 수록 서버 저장소에 저장될 세션의 양이 증가하므로 서측 부담 증가

7. SSR 방식에 적합

 

- 토큰 방식
비유를 하여 설명하자면, 우리의 일상생활에서 자주 보이는 입장권 같은 개념이다.
예를들어, 놀이공원 티켓처럼
사용자의 인원수, 사용자의 티켓이 자유이용권인지, 기구 탑승 횟수 제한이 된 티켓인지 여부가 적혀있고, 티켓의 유효기간도 적혀있을 것이다.
토큰도 같은것이다.
사용자의 ID, 권한정보 와 같은 사용자 정보가 적혀있고 그 토큰을 클라이언트에게 발행해 주고 서버에서는 더 이상 그 티켓을 관리하지 않는다.
그렇다면 해당 티켓을 변조할 경우 어떻게 해야할지 궁금할것이다. 그것은 차차 알아보자.

- 토큰 기반 특징

1. 토큰에 포함된 사용자 정보는 서버에서 관리하지 않음.

2. 서버에서 생성하여 클라이언트에게 발행한 토큰은 클라이언트의 request시 헤더에 포함시켜 전송

3. 토큰에는 사용자 정보와 같은 내용들까지 모두 포함되어 있기 때문에 상대적으로 네트워크 트래픽이 증가

4. 서버에서 토큰을 아예 관리하지 않는다면, 보안면에서 좋지 못함.

5. 로그인 중인 유저에 대한 관리를 서버에서는 전혀 할 필요 없으므로, 확장성 면에서 좋고 "세션 불일치" 같은 일들이 존재하지 않는다.

6. 토큰에 포함되는 정보 중 사용자의 정보도 포함되어 있는데, 이 정보는 고도의 알고리즘으로 암호화된 상태가 아니기 때문에 언제든지 탈취되어 볼 수 있다. 그러므로 토큰에는 정말 민감한 사용자 정보는 담지 않아야 한다.

7. 서버에서는 토큰을 발행하여 전달한 유저에 대한 정보를 관리 하지 않기때문에, 불법 유저를 즉각적으로 로그아웃시켜 내쫓는다던가 하느 행위가 불가능하다.

8. CSR에 적합한 방식이다.

 

 

JWT (Json Web Token) 토큰이란?

토큰 기반의 인증방식 중 대표적인것이 JWT이다.
Json 형식의 데이터를 토큰으로 만들어 발행하는 방식이다.

 

JWT 사용시 보통 다음과 같이 두가지의 토큰을 생성한다.

 

1. 액세스 토큰 (Access Token)

2. 리프레쉬 토큰 (Refresh Token)

 

이유는, 위에서 말했던 토큰방식의 특징 중 7번째의 내용인

"서버에서는 토큰을 발행하여 전달한 유저에 대한 정보를 관리 하지 않기때문에, 불법 유저를 즉각적으로 로그아웃시켜 내쫓는다던가 하느 행위가 불가능하다."

라는 한계를 보완하기 위해서이다.

 

만약, 특정 클라이언트의 액세스 토큰을 누군가가 탈취를 하였을 경우,

탈취한 누군가는 해당 토큰을 포함하여 불법적인 요청을 보낼 경우에 항상 유효한 처리가 될것이다.

그럴 경우에, 서버에서는 세션과 같은 클라이언트의 로그인 정보 같은 데이터를 가지고 있지 않기 때문에, 해당 로그인 상태를 강제로 로그아웃 시킨다던가 하는 강제적인 조치가 불가능하다.

 

이럴 경우를 대비해서, "액세스 토큰", "리프레쉬 토큰" 두개를 클라이언트에게 발행하는데,

이때, 서버에서는 "리프레쉬 토큰" 에 상응하는 값을 서버 저장소에 저장한다.

그리고선 일반적인 상황에서의 요청시에는 액세스 토큰을 서버로 보낸다.

그럼 서버는 해당 토큰의 유효성만 검사를 하면된다. (세션과 같이 DB를 뒤져서 해당 유저의 로그인 상태가 유요한것인지 체크 필요 X)

그러다가 액세스 토큰의 유효기간이 지났을 경우에, 클라이언트는 서버로 "액세스 토큰" 대신에!

"리프레쉬 토큰"을 request와 함께 보낸다.

그럼 서버는 서버 저장소에 있는 리프레쉬 토큰의 상응하는 값이 존재하는지.

그리고 유효한 리프레쉬 토큰인지, 그리고 유효기간이 남아있는지 같은 조건을 검사한 후 

다시 "액세스 토큰"을 발행하여 준다.

 

 

  • JWT 의 구조

    서버가 클라이언트에게 발행하여 주는 JWT의 기본적은 구조는 아래와 같다.

출처 : https://povio.com/blog/handling-authentication-in-spa-with-jwt-and-cookies/

 

 

위에 구조를 더 상세히 본다면 아래와 같다.

위에 부분은 헤더, 페이로드, 시그니쳐 부분이 인코딩 되기 전의 모습이고,

아래의 긴 문자열 형태가 JWT의 실제 모습이다.

참고로 시그니쳐 부분은 인코딩 되기 전까지 존재하지 않는다.

어떻게 만들어지는지에 대해 설명한 것이다.

출처 : https://ssup2.github.io/theory_analysis/JWT/

 

- 헤더

헤더의 데이터는 인코딩 전엔 Json 형태이다.

그리고 그 데이터로는 

typ : 어떤 종류의 토큰인지 

alg : 어떤 종류의 알고리즘으로 시그니쳐가 만들어졌는지

위 내용은 필수 데이터이다.

 

- 페이로드

페이로드의 데이터는 인코딩 전엔 Json 형태이다.

그리고 그 데이터로는 

사용자 정보, 그리고 해당 토큰의 유효기간과 같은 필수 정보들과

기타 필요의 의한 정보들이 들어간다.

 

- 시그니쳐

시그니쳐의 데이터는 

헤더를 base64로 인코딩한 값, 페이로드를 base64로 인코딩한 값, 시크릿키, 

이 세 요소를 이용하여 암호화 알고리즘 으로 생성한 암호키가 위치하게 된다.

이말인 즉, 시그니쳐 부분은 헤더와 페이로드처럼 인코딩전 상태라는것이 존재하지 않는다.

그리고 이때 사용되는 암호화 알고리즘은 헤더 부분에 있던 alg키에 할당된 알고리즘 방식으로 암호화 된다.

 



 

  • JWT의 인증 절차

1. 클라가 서버에게 ID, PWD를 보내서 로그인 요청

2. 서버에서는 ID, PWD를 서버 저장소의 데이터와 비교하여 인증 처리

3. 인증이 완료되면 "액세스 토큰", "리프레쉬 토큰" 발행

 - 사용자 정보와 같은 데이터는 "리프레쉬 토큰"에 담을 필요 없음

    리프레쉬 토큰은 액세스토큰을 재 발행해줄 용도로만 쓰이기 때문.

4. 서버가 발행해준 토큰 2개를 클라는 Cookie, Local Storage 과 같은 임의의 공간에 저장

5. 클라이언트는 앞으로 request를 보낼때 Header 또는 Cookie에 토큰을 담아 전송

6. 서버는 해당 토큰이 유효한 토큰인지 검증 후 유효하다면 로그인한 유저로 인정

 

 

 

여기서 의문! 만약 사용자가 토큰의 payload 부분을 변조한다면?

JWT의 Signature 부분으로 인해 변조됨을 서버에서 확인할 수 있다.

앞서 말했듯이 Signature는 3가지 요소가 필요하다.

 

1. 인코딩된 header

2. 인코딩된 payload

3. 서버가 가지고 있는 시크릿키

 

만약, 

클라가 payload를 변조하여 jwt를 서버로 보냈다고 치자. (header와 payload는 base64로 인코딩 됬을 뿐이기 때문에, 암호화된것이 아니다. 그러므로 쉽게 디코딩도 가능하다)

서버에서는 jwt 가 들어왔을때

해당 jwt의 

header, payload 부분과 서버에서 가지고 있는 시크릿키를 이용하여 토큰을 만들때처럼 암호화 알고리즘으로

signature를 생성하여 볼것이다.

그럼 만들어진 signature는 클라이언트가 가져온 signature와 다르게 생성이 될것이므로

해당 jwt가 변조 되었음을 알수가 있다!

  

 

  • JWT 장,단점
    - 장점
    1.  상태를 유지하지 않으며, 확장성 있는 애플리케이션에 용이
    -  서버가 클라이언트의 상태 정보를 가지고 있지 않아도 되며,
       만약 여러대의 서버가 존재할 경우, 하나의 토큰으로 모든 서버에서 인증을 받을 수 있다.
       세션 기반일 경우, 여러대의 서버에서 동일한 세션정보를 항상 일치시켜 갖고 있어야 한다. (세션 정보의 불일치가
    발생 될 수도 있다)

    2. 클라가 request마다 자신의 인증 정보를 보낼 필요 없다
    - id, pwd 같은걸 계속 보낼 필요 없다는 것이다. 당연한 얘기다

    3.  인증을 담당하는 시스템을 다른 플랫폼으로 분리하는 것이 용이
    - 우리의 서버에서 인증을 담당할 필요 없이, 타 플랫폼 (구글, 카카오) 에서 인증을 맡길 수 있다.

    4. 권한 부여에 용이


    - 단점
    1. Payload는 디코딩이 용이
    - 그러므로 만약 토큰이 탈취 당했을때, 사용자 정보를 쉽게 볼 수  있다.

    2. 토큰의 길이가 길어지면 네트워크에 부하를 줄수 있음
    - 세션의 경우는 기본적으로 클라가 세션 ID만 보내면 되지만, 토큰은 암호화 됬다고 하지만 그 안에 유저 정보가 모두 들은 정도의 크기이다. 그러므로 상대적으로 부하가 됨.

    3. 토큰 자동삭제 불가
    - 한번 생성하여 발행된 토큰은 서버에서 임의로 삭제가 불가능하기 때문에, 
    꼭 유효기간을 추가해야한다.

 

 

참조 : https://www.youtube.com/watch?v=1QiOXWEbqYQ 

https://www.youtube.com/watch?v=zC5dLbZMAW0