**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를 사용하여 전달되는 토큰을 암호화하고, 토큰의 만료 시간을 짧게 설정하여 보안 위험을 줄이는 것이 좋습니다.
'Spring Security' 카테고리의 다른 글
SecurityContext, SecurityContextHolder, 스레드 처리 방식 (1) | 2024.10.29 |
---|---|
UserDetailsService, PasswordEncoder, AuthenticationProvider (0) | 2024.10.29 |
SHA-256 (4) | 2024.10.28 |
자체 서명된 인증서 생성하기 (1) | 2024.10.28 |
Credential, Principal (1) | 2024.10.28 |