Spring_19_JWT

OngTK·2025년 10월 23일

Spring

목록 보기
19/25

🔐 JWT (JSON Web Token) 정리

웹·앱 환경에서 사용되는 토큰 기반 인증 방식에 대한 정리.
인증(Authentication)과 인가(Authorization)를 분리하고,
세션(Session)보다 효율적이며 확장성 높은 인증 구조를 제공함.


🧭 인증 vs 인가

구분설명
인증 (Authentication)사용자가 누구인지 확인하는 과정
인가 (Authorization)인증된 사용자가 접근 권한이 있는지 확인하는 과정

🔧 인증 방법

구분설명
세션 (Session)서버 메모리에 사용자 정보를 저장하여 인증 유지 (Spring Security 등)
쿠키 (Cookie)브라우저에 토큰/식별정보 저장 (보조 보안 수단으로 JWT와 함께 사용)
JWT (JSON Web Token)서버 상태를 저장하지 않고 클라이언트에 인증 정보를 담는 토큰 방식

🧱 JWT 정의

  • JWT (JSON Web Token)
    : JSON 형식의 데이터를 안전하게 주고받기 위한 토큰 기반 인증 방식

🎯 JWT 목적

  • 웹(Web) / 모바일(App) 환경에서 인증과 권한 부여(Authorization) 관리에 사용
  • 세션을 대체하여 서버의 부하 감소
  • REST API 환경에서 인증에 적합

⚙️ JWT 장점

  • HTTP 지원: Header에 토큰을 포함하여 요청 가능
  • 보안성: 비밀키 기반의 서명(Signature)으로 변조 방지 (기본 알고리즘: HS256)
  • 무상태성 (Stateless): 서버가 클라이언트 상태를 직접 관리하지 않아 확장성↑

🧩 JWT 구조

헤더(Header).페이로드(Payload).서명(Signature)

구성요소설명
Header알고리즘 정보, 토큰 타입(JWT)
Payload실제 데이터(클레임, 발급시간 등)
Signature헤더+페이로드를 비밀키로 서명한 값

💡 비밀키(secret key)는 개발자가 직접 지정한 난수 문자열을 사용해야 하며,
외부에 노출되면 절대 안 됨.


🚀 JWT 확장

연동 대상설명
쿠키 (Cookie)JWT를 클라이언트 브라우저에 저장
Redis (NoSQL)분산 서버 간 토큰 공유 및 블랙리스트 관리에 사용 가능

⚙️ JWT 사용법

1️⃣ Gradle 의존성

implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

2️⃣ 비밀키 생성

@Service
@RequiredArgsConstructor
public class JwtService {

    // [1] SHA-256 알고리즘을 사용한 비밀키 (32자 이상)
    private final String secretSample = "12345678901234567890123456789012";

    // [2] 문자열 기반으로 HMAC-SHA 키 생성
    private final Key secretKeySample =
            Keys.hmacShaKeyFor(secretSample.getBytes(StandardCharsets.UTF_8));
}

StandardCharsets.UTF_8 은 한글·특수문자 포함 시 필수.
난수는 잊지 않도록 코드 내 직접 관리 또는 환경변수로 관리하는 것이 좋음.


3️⃣ 토큰 관련 메서드

(1) 토큰 생성

public String createTokenSample(String data) {
    String token = Jwts.builder()
            // claim(key, value): 토큰에 넣을 데이터
            .claim("key", data)
            // 토큰 발급 시간
            .setIssuedAt(new Date())
            // 토큰 만료 시간 (현재 + 30초)
            .setExpiration(new Date(System.currentTimeMillis() + 1000 * 30))
            // HS256 알고리즘으로 서명
            .signWith(secretKeySample, SignatureAlgorithm.HS256)
            .compact();

    return token;
}

(2) 토큰 검증 및 유효성 확인

public boolean checkTokenSample(String token) {
    try {
        Jwts.parser()
                .setSigningKey(secretKeySample) // 서명 검증용 키
                .build()
                .parseClaimsJws(token);          // 토큰 검증
        return true;
    } catch (JwtException e) {
        System.out.println("토큰 없음 또는 유효하지 않음");
        return false;
    }
}

(3) 토큰에서 데이터 추출

public String payloadTokenSample(String token) {
    try {
        Claims claims = Jwts.parser()
                .setSigningKey(secretKeySample)
                .build()
                .parseClaimsJws(token)
                .getBody(); // 검증 후 클레임 반환

        System.out.println("claims = " + claims);
        return claims.get("key", String.class);
    } catch (Exception e) {
        return null;
    }
}

(3-2) 특정 필드 추출용 함수

public String getUid(String token) {
    return getClaims(token).get("uid", String.class);
}

public String getUrole(String token) {
    return getClaims(token).get("urole", String.class);
}

🧠 추가 팁

항목설명
만료시간짧게 설정 후 Refresh Token으로 재발급 구조 구성
비밀키 관리.env 또는 Spring application.yml에 분리
Redis 연동토큰 블랙리스트 저장, 로그아웃 시 즉시 무효화
JWT + Cookie쿠키에 HttpOnly, Secure, SameSite 옵션 설정 필수
CORS 허용JWT를 헤더에 담을 경우, Access-Control-Allow-HeadersAuthorization 추가 필요

✅ 핵심 요약

구분설명
JWT 구조Header.Payload.Signature
서명 알고리즘HS256 (대칭키 기반)
장점무상태, 확장성, 보안성
단점토큰 크기 증가, 만료 전까지 무효화 불가
권장 조합JWT + Redis / JWT + Cookie

profile
2025.05.~K디지털_풀스택 수업 수강중

0개의 댓글