JWT 정의

JWT(JSON Web Token)는 웹 표준에 따른 인증 토큰 방식으로, 주로 사용자 인증 및 정보 전달에 사용된다.

JWT는 서버가 클라이언트의 상태를 저장하지 않고도 인증 정보를 주고받을 수 있게 해주는 방법으로, 특히 RESTful API와 함께 많이 사용된다.

특징

•토큰 자체에 정보를 담고 있어, 서버에 세션을 저장할 필요 없음
•URL, HTTP 헤더 등에 넣기 적합한 짧은 문자열
•사용자 정보나 권한 등을 토큰 안에 포함할 수 있음
•비밀키를 통해 위변조 여부 검증 가능

주의사항

•중요한 정보는 Payload에 넣지말기 (Base64 인코딩일 뿐 암호화 아님)
•서명 검증은 항상 필수
•적절한 만료 시간 설정 필요
•HTTPS 환경에서 사용 권장

JWT 구조

JWT는 3개의 파트 Header, Payload, Signature로 구성되며 각 파트 별 역할은 아래와 같다.

구성 요소 설명 예시
Header 토큰의 타입의 서명에 사용된 해싱 알고리즘을 지정
일반적으로 HS256 또는 RS256 등을 사용함
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload 실제 담고 싶은 정보를 포함하는 부분
{
  "sub": "user123",
  "name": "홍길동",
  "exp": 1718868300
}
Signature 토큰이 위변조되지 않았는지를 검증하기 위한 서명
Header와 Payload를 base64 인코딩 후 비밀 키를 이용해 서명
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

 
아래는 0.12.6 버전을 예시로 작성한 java 코드입니다.

의존성 추가 maven기준
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-api</artifactId>
  <version>0.12.6</version>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-impl</artifactId>
  <version>0.12.6</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-jackson</artifactId> <!-- 또는 jjwt-gson 중 택1 -->
  <version>0.12.6</version>
  <scope>runtime</scope>
</dependency>

https://mvnrepository.com/ maven 관련 참고.

java 코드, 생성과 검증
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;

public class JwtValidator {

    // 256비트(32바이트) 이상의 시크릿 키
    private static final String SECRET = "your-256-bit-secret-your-256-bit-secret";
    private static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));

    public static void main(String[] args) {
        String jwt = generateToken("testUser");
        System.out.println("생성된 JWT: " + jwt);

        Claims claims = validateToken(jwt);
        if (claims != null) {
            System.out.println("검증 성공! Subject: " + claims.getSubject());
            System.out.println("만료 시간: " + claims.getExpiration());
        }
    }

    // JWT 생성
    public static String generateToken(String subject) {
        long now = System.currentTimeMillis();
        return Jwts.builder()
                .subject(subject)
                .issuedAt(new Date(now))
                .expiration(new Date(now + 1000 * 60 * 60 * 24)) // 하루 뒤 만료
                .signWith(KEY, Jwts.SIG.HS256)
                .compact();
    }

    // JWT 검증
    public static Claims validateToken(String token) {
        try {
            JwtParser parser = Jwts.parser()
                    .verifyWith(KEY)
                    .build();

            return parser.parseSignedClaims(token).getPayload();

        } catch (ExpiredJwtException e) {
            System.out.println("JWT 만료됨: " + e.getMessage());
        } catch (UnsupportedJwtException e) {
            System.out.println("지원되지 않는 JWT: " + e.getMessage());
        } catch (MalformedJwtException e) {
            System.out.println("잘못된 형식의 JWT: " + e.getMessage());
        } catch (SecurityException e) {
            System.out.println("서명 검증 실패: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("JWT 검증 중 오류: " + e.getMessage());
        }
        return null;
    }
}


JWT 는 토큰이 발급자에 의해 만들어졌고, 중간에 변조되지 않았음을 보장한다, 하지만 JWT 만으로는 사용자 인증을 완전히 보장하지 않으므로 JWT를 발급받을때의 보안절차 + JWT 유효기간 관리를 하여야 한다.

+ Recent posts