Spring Security / / 2024. 10. 28. 17:22

JSON Web Token

**JSON Web Token (JWT)**은 주로 클라이언트와 서버 간에 사용자 인증정보 전달을 위해 사용하는 JSON 기반의 토큰입니다. JWT는 특히 웹 애플리케이션에서 많이 사용되며, 사용자 로그인 후 발급된 토큰을 통해 사용자가 이후 요청에서도 지속적으로 인증을 유지할 수 있도록 해줍니다.

 

JWT의 구성 요소

 

JWT는 크게 헤더(Header), 페이로드(Payload), **서명(Signature)**의 세 부분으로 나누어집니다.

 

1. 헤더(Header):

헤더는 토큰의 유형과 서명 알고리즘을 지정하는 정보를 포함합니다. 일반적으로 alg는 서명 알고리즘을 나타내고, typ는 JWT임을 나타냅니다.

예시:

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

 

2. 페이로드(Payload):

페이로드에는 토큰에 담길 **실제 정보(Claims)**가 들어갑니다. 정보에는 사용자 ID, 권한, 토큰 만료 시간 등의 사용자 관련 데이터가 포함될 수 있습니다.

페이로드는 크게 세 가지 Claim으로 구성됩니다:

등록된 Claim: iss(발급자), sub(주제), aud(청중), exp(만료 시간) 등의 표준화된 정보입니다.

공개 Claim: 사용자 정의 데이터를 추가할 수 있는 필드입니다.

비공개 Claim: 발급자와 수신자 간에만 사용하는 비공개 데이터입니다.

예시:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

 

3. 서명(Signature):

서명은 헤더와 페이로드의 무결성을 보장하기 위해 사용됩니다. 토큰이 변조되지 않았음을 확인하기 위해 생성하는 해시 값입니다.

서명은 헤더, 페이로드, 비밀 키를 기반으로 생성됩니다. 예를 들어, HMAC SHA-256 알고리즘을 사용한다면, HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)와 같은 방식으로 서명이 생성됩니다.

 

이렇게 만들어진 JWT는 다음과 같은 형태로 나타납니다:

header.payload.signature

 

각각의 부분은 Base64Url 인코딩되어 있으며, 점(.)으로 구분됩니다.

 

JWT의 동작 원리

 

JWT는 상태 비저장(stateless) 방식으로 동작합니다. 서버는 JWT를 발급하지만, 별도의 세션을 저장하지 않고, 클라이언트가 JWT를 전달하면 이 토큰을 기반으로 사용자 정보를 확인합니다.

 

1. 인증 요청:

사용자가 로그인 시도 시, 서버는 사용자 인증을 검증하고 사용자에게 JWT를 발급합니다.

2. 클라이언트 저장:

클라이언트(브라우저, 모바일 등)는 이 JWT를 쿠키나 로컬 스토리지 등에 저장해둡니다.

3. 요청 시 토큰 전달:

사용자는 인증이 필요한 요청 시 JWT를 함께 보냅니다. 일반적으로 HTTP 헤더의 Authorization 필드에 Bearer 방식으로 전달합니다.

예: Authorization: Bearer <JWT>

4. 서버에서 토큰 검증:

서버는 전달받은 JWT의 서명을 검증하여 변조되지 않았음을 확인합니다. 유효한 JWT라면 페이로드를 기반으로 사용자 정보를 확인하고 요청을 처리합니다.

 

JWT의 장점과 단점

 

장점

 

1. 세션 유지 불필요: 상태 비저장 방식이므로 서버에서 세션을 유지할 필요가 없어 확장성이 높습니다.

2. 독립적인 정보 전달: JWT는 서버와 클라이언트 간 정보를 독립적으로 전달하므로, 사용자는 하나의 로그인 상태를 유지하면서 여러 서비스에 접근할 수 있습니다.

3. 간편한 사용: URL, 헤더, 쿠키 등 다양한 방법으로 전달이 가능하고, 다른 인증 메커니즘보다 간편하게 사용할 수 있습니다.

 

단점

 

1. 토큰 크기 문제: JWT는 페이로드에 정보를 포함하기 때문에 길어질 수 있으며, 많은 데이터를 포함하면 전송에 부담이 됩니다.

2. 변경 어려움: 서버에서 JWT를 변경하거나 무효화하기 어렵습니다. 보통 토큰 만료 시간을 설정하고, 재발급하는 방식으로 관리합니다.

3. 보안 이슈: 토큰을 클라이언트에 저장하므로 탈취될 경우 위험할 수 있습니다. HTTPS를 사용하여 암호화된 통신을 사용하는 것이 중요합니다.

 

JWT와 세션 기반 인증의 차이점

 

세션 기반 인증은 서버가 클라이언트의 인증 정보를 세션에 저장하고, 클라이언트는 세션 ID를 사용해 인증 상태를 유지합니다.

JWT 기반 인증은 토큰 자체에 인증 정보를 포함하고, 서버에 상태 정보를 저장하지 않는 상태 비저장 방식입니다.

 

JWT 사용 예시 (Java)

 

Spring Security와 JWT를 사용하여 인증을 구현하는 예제입니다.

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtTokenProvider {
    private final String secretKey = "yourSecretKey";
    private final long validityInMilliseconds = 3600000; // 1시간

    // JWT 생성
    public String createToken(String username) {
        Claims claims = Jwts.claims().setSubject(username); // 사용자 이름 설정
        Date now = new Date();
        Date validity = new Date(now.getTime() + validityInMilliseconds);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }

    // JWT 검증
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

 

1. createToken 메서드: 사용자 이름을 기반으로 JWT를 생성하고, 만료 시간과 서명 알고리즘을 설정합니다.

2. validateToken 메서드: 전달받은 토큰을 비밀 키로 검증하여 유효한 토큰인지 확인합니다.

 

이 코드는 JWT를 사용한 인증 흐름의 일부이며, 실제로는 Spring Security 필터를 통해 인증 요청에서 JWT를 추출하고 검증하는 과정이 필요합니다.

 

JWT의 활용 예

 

API 인증: JWT는 API 인증에서 사용자 세션을 유지하지 않고도 인증을 관리할 수 있게 해줍니다.

마이크로서비스: 서비스 간에 사용자 인증 정보를 전달하는 데 사용되며, JWT를 통해 서비스 간 인증을 통합할 수 있습니다.

싱글 사인온(SSO): 여러 서비스에서 하나의 로그인 상태를 유지할 수 있게 해줍니다.

 

요약

 

JWT는 인증 정보와 클레임을 포함한 JSON 기반의 토큰으로, 클라이언트-서버 간의 무상태 인증에 유용하게 사용됩니다. 또한, 보안성이 요구되는 환경에서는 HTTPS를 사용하여 전달되는 토큰을 암호화하고, 토큰의 만료 시간을 짧게 설정하여 보안 위험을 줄이는 것이 좋습니다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유