JwtUtil 관련 기록

가온·2025년 5월 31일

요즘 백엔드를 다시 만지작 거리고 있다.
작년까지만 해도 그냥 복붙하고 실행되면 일단 되는구나 했는데,
개념을 익히다 보니 조금씩 이해되는 부분이 있는 것 같다.

그리고 다시 돌아보니 내가 이전에 만든 서버는 보안이 엉망진창이었다.
그러나 이제는 그러면 안되는 단계에 왔으니 모르는 부분은 gpt에 물어가며 정리하고 있다.
이론 공부가 되고 나서 코드를 작성하게 되니 질문도 어떻게 해야 할 지 좀 알 것 같다.

📓 JwtUtil 클래스 함수 설명 & 보안 개념 정리


🔐 getSigningKey()


private Key getSigningKey() {
    return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
}
  • 역할: JWT의 서명(Signature) 생성을 위한 서명용 Key 객체를 생성
  • 입력: .env에서 불러온 비밀 키 문자열 (secret)
  • 출력: javax.crypto.SecretKey (HMAC용)
  • 내부 동작:
    • 문자열 키 → 바이트 배열 → HMAC-SHA256에 사용할 수 있는 Key로 변환

🔐 보안 개념

  • 전자서명: 서버가 만든 JWT가 위조되지 않았음을 검증하는 데 사용됨
  • 대칭키 방식: 서명 생성과 검증에 같은 키(secret) 를 사용
  • HMAC-SHA256: 해시 알고리즘(SHA-256)과 키를 결합한 서명 방식

🧾 generateToken(String email)

public String generateToken(String email) {
    return Jwts.builder()
        .setSubject(email)
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
        .signWith(getSigningKey(), SignatureAlgorithm.HS256)
        .compact();
}
  • 역할: 사용자의 JWT 토큰 생성
  • 담기는 정보 (Claims):
    • sub: 사용자 이메일
    • iat: 토큰 발급 시간
    • exp: 만료 시간
  • 서명 방식: HMAC-SHA256 + getSigningKey()

📬 extractClaims(String token)


public Claims extractClaims(String token) {
    return Jwts.parserBuilder()
        .setSigningKey(getSigningKey())
        .build()
        .parseClaimsJws(token)
        .getBody();
}
  • 역할: 토큰을 파싱하여 내부의 Payload(=Claims) 추출
  • 보안 기능: 자동으로 서명 유효성 검증
    • 서명이 위조되었거나 변조되면 예외 발생

isTokenValid(String token, String email)

public boolean isTokenValid(String token, String email) {
    final String tokenEmail = extractClaims(token).getSubject();
    return (tokenEmail.equals(email) && !isTokenExpired(token));
}
  • 역할: 토큰이 유효한지 검증
  • 검사 내용:
    • 토큰에 저장된 이메일이 일치하는가?
    • 토큰이 만료되지 않았는가?

isTokenExpired(String token)

private boolean isTokenExpired(String token) {
    return extractClaims(token).getExpiration().before(new Date());
}
  • 역할: 토큰 만료 시간(exp)이 현재 시간보다 이전인지 확인
  • 출력:
    • true: 만료됨
    • false: 유효함

📌 핵심 개념 요약

용어설명
JWT (JSON Web Token)사용자의 인증 정보를 담은 JSON 기반의 토큰
ClaimsJWT 내부의 사용자 정보 (email, iat, exp 등)
전자서명JWT 위조 방지를 위한 암호화 서명. 발급자가 진짜인지 확인 가능
HMAC-SHA256SHA256 해시 + 비밀키 기반의 전자서명 방식
대칭키서명 생성과 검증에 같은 키를 사용 (secret 키)

✅ Q1. HMAC-SHA256은 전자서명인가?

전자서명의 한 방식

단, 일반적인 전자서명은 공개키/개인키를 사용하는 비대칭키 방식이고,

HMAC대칭키 기반의 서명 방식

🔑 HMAC-SHA256:

secret key + SHA-256 해시 알고리즘

👉 이걸 이용해 메시지를 서명함으로써, 변조 여부를 검증할 수 있음.


✅ Q2. 서명의 주체는 누구?

✔️ 서버

  • 서버가 secret key를 가지고 있고,
  • 토큰을 만들고 서명하며,
  • 클라이언트가 보낸 JWT를 다시 서명 검증할 수 있는 주체도 서버뿐

✅ Q3. Claim이 정보?

JWT 내부의 payload 영역을 Claims 라고 부름.

이 안에 유저 정보, 권한, 만료일 등 다양한 값이 들어갈 수 있음.

예시:

{
  "sub": "user@example.com",
  "iat": 1715678880,
  "exp": 1715765280
}

✅ Q4. 토큰엔 뭐가 담겨 있나?

정리하면 JWT는 세 부분으로 구성됨:


HEADER.PAYLOAD.SIGNATURE
  • Header: 어떤 알고리즘으로 서명했는지 (예: HMAC-SHA256)
  • Payload (Claims): 이메일, 생성시간, 만료시간 등
  • Signature: 위 두 개를 서버의 secret key로 HMAC-SHA256 처리한 결과

🔐 이 서명을 통해 토큰의 무결성(변조되지 않았는지) 를 확인


✅ Q5. 만료 여부 검사는 어떻게?


return claims.getExpiration().before(new Date());

✔️그냥 비교

  • 만료 시간(exp)과 현재 시간을 비교해서,
  • 현재가 더 늦으면 → 만료됨 (true)

확실히 AI가 코드를 작년보다 훨씬 잘 짜주긴 하는데, 내가 기본적인 것을 알고 있어야 하는 것은 여전한 것 같다.
그리고 이론을 공부하면서 하는 것과 아닌 것에 질문 차이도 스스로 느끼고 있다.

까먹지 말고 정리해야지...

0개의 댓글