[Spring + React] 게시판 프로젝트 - (2) JWT 로그인 프로세스

김희정·2024년 7월 25일
0

Spring+React

목록 보기
2/2

썸네일

💎 들어가며

React에서는 JWT로 로그인 기능을 구현한다는 것은 익히 들어 알고 있었지만, 왜 JWT를 이용하여 로그인을 해야하는 지는 감이 안잡혔습니다.

Spring + React 스택을 사용하면서 기존에 사용하던 Spring Security의 FormLogin 기능을 구조적으로 이용할 수 없기 때문에 JWT를 사용해야 된다는 것을 깨닫게 되었습니다.

  • 기존의 Jsp 혹은 Thymeleaf 등의 Template Engine은 SSR (Server-Side-Rendering)으로, 서버 페이지이기 때문에 세션 정보를 관리할 수 있음
  • 하지만 프론트를 프레임워크로 구현하게 되면 CSR (Client-Side-Rendering)으로, 서버 정보를 유지할 수 없음. ⇒ 유저를 어떻게 판별할 것인가?
  • 정답은 JWT!

1. JWT

1.1 Definition

JWTJson Web Token의 약자로 JSON 객체로 정보를 안전하게 전송하는 방법을 정의하는 공개된 표준(RFC 7519)입니다.

JWT는 HMAC 알고리즘으로 비밀키를 사용하여 서명될 수 있고, RSA나 ECDSA를 사용한 공개/비공개 키 쌍으로도 서명될 수 있습니다.


1.2 JWT Structure

JWT 토큰에는 Header, Payload, Signature로 세가지 구성요소로 나뉘어 있으며, 아래와 같은 형태를 지닙니다.

HHHHH.PPPPP.SSSSS

출저: What is a JSON Web Token (JWT)?


토큰의 첫번째 부분인 헤더(Header)에는 서명시 사용하는 서명 암호화 알고리즘(alg), 사용할 타입(typ) 등 메타 정보가 담겨있습니다.

보통 헤더는 두 부분으로 구성됩니다.

  • 토큰의 종류 : JWT
  • 사용되는 서명 알고리즘 : HMAC, SHA256, RSA
{
  "alg": "HS256",
  "typ": "JWT"
}

그리고 이 내용들은 JWT를 구성하기 위해 Base64Url로 인코딩됩니다.


Payload

토큰의 두번째 부분인 페이로드(Payload)에는 토큰에 담을 정보가 들어있으며, 담는 정보의 한 조각을 클레임(claim)이라고 부릅니다.

클레임에는 크게 세가지 분류로 나뉘어 있습니다.

  1. 등록된(registered) 클레임
  2. 공개(public) 클레임
  3. 비공개(private) 클레임

등록된 클레임

먼저 등록된 클레임은 서비스에서 필요한 정보들이 아닌 토큰에 대한 정보를 담기 위해 이름이 이미 정해진 클레임들입니다.

  • iss: 토큰 발급자 (issuer)
  • sub: 토큰 제목(subject)
  • aud: 토큰 대상자(audience)
  • exp: 토큰 만료시간(expiraton), 형식은 NumericDate로 되어 있어야합니다. (예: 1480849147370)
  • nbf: Not Before를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
  • iat: 토큰이 발급된 시간(issued at), 이 값을 사용하여 토큰의 age가 얼마나 되었는지 판단할 수 있습니다.
  • jti: JWT의 고유 식별자로서, 주로 중복적인 처리 방지를 위해 사용됩니다.

각 클레임들은 선택적(optional)으로 포함할 수 있습니다.


공개 클레임

공개 클레임은 사용자 정의 클레임으로, 공개용 정보를 위해 사용됩니다. 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓습니다.

{
    "https://localhost/jwt_claims/is_admin": true
}

비공개 클레임

비공개 클레임은 사용자 정의 클레임으로, 서버와 클라이언트 사이에 임의로 지정한 정보를 저장합니다.

{
    "username": "admin"
}

완성된 예시 페이로드

{
  "username": "admin",
  "auth": "ROLE_USER,ROLE_ADMIN",
  "https://localhost/jwt_claims/is_admin": true
  "exp": 1724135496,
  "iat": 1724133696
}

Signature

토큰의 마지막 부분인 서명(Signature)은 토큰을 인코딩하거나 유효성을 검증할 때 사용하는 고유한 암호화 코드입니다.

서명(Signature)을 만들기 위해서는 위에서 만든 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더(Header)에서 정의한 알고리즘으로 해싱하고, 이 값을 다시 BASE64로 인코딩하여 생성합니다.

  1. 헤더, 페이로드 Base64 인코딩
  2. 인코딩한 값을 해싱 (Header의 'alg' 알고리즘 + 비밀 키)
  3. 해싱한 값을 다시 Base64 인코딩
  4. Signature 완성!

2. Spring + React 로그인

Spring과 React는 각각 Server, Client로 볼 수 있습니다.

Process

로그인 프로세스는 다음과 같습니다.

JWT 로그인 프로세스

  1. 클라이언트 단에서 사용자가 id, password를 이용해 로그인을 요청합니다.
  2. 서버에서 사용자 확인시 미리 정의된 Secret Key와 알고리즘을 통해 Access Token을 발급합니다. (+ 이 때 Refresh Token도 함께 고려될 수 있습니다)
  3. 클라이언트에 로그인 성공과 함께 jwt 토큰을 전달합니다
  4. 클라이언트는 각 서비스 요청시에 헤더에 jwt 토큰을 넣어 전달합니다.
  5. 서버는 요청 처리 전 JWT 서명을 체크하고, JWT 토큰을 분해하여 사용자 정보를 확인합니다.
  6. 서버는 클라이언트 요청에 대한 응답을 전달합니다

in Spring

Spring에서는 다음과 같은 항목을 구현해야 합니다.

  • DB 연동하여 로그인 요청 프로세스 구현 (AuthenticationProvider 구현)
  • 로그인 시 JWT 토큰 발급 (Token Provider 구현)
  • Request 요청시 Header에서 JWT 토큰을 통해 사용자 인증 정보 획득 (JwtRequestFilter 구현)

in React

React에서는 다음과 같은 항목을 고려해야 합니다.

  • 로그인 요청시 받은 JWT 토큰 저장
  • 매 요청시 헤더에 JWT 토큰 추가


💎 References


💎 마치며

이번 포스팅에서는 다음과 같은 항목에 의해 포스팅하였습니다.😊

  • JWT란 무엇인지
  • JWT를 이용하여 Spring과 React가 어떤 프로세스로 동작하는지
  • 각 프로그램에서 어떤 것을 구현해야 되는지

다음 포스팅에서는 Spring에서 구현해야될 항목에 대해 포스팅하겠습니다~🙌

profile
Java, Spring 기반 풀스택 개발자의 개발 블로그입니다.

0개의 댓글