본문 바로가기
코딩 공부/web & Java

[JWT] JWT 0.12.5 최신화 문제 해결

by 현장 2024. 7. 20.

예전 공부할 때, 사용했던 JWT 및 Key 생성을 직접 사용해 보고 그때보다 좀 더 최신 버전을 사용하고 싶었습니다.

public class JwtTokenUtils {
    // 토큰에서 username 가져옴
    public static String getUserName(String token, String key) {
        return extractClaims(token, key).get("userName", String.class);
    }
    
    // 종료 시간
    public static boolean isExpired(String token, String key) {
        Date expiredDate = extractClaims(token, key).getExpiration();

        return expiredDate.before(new Date());
    }
	
    // 토큰에서 clais(정보) 추출
    private static Claims extractClaims(String token, String key) {
            return Jwts.parserBuilder().setSigningKey(getKey(key))
                    .build().parseClaimsJws(token).getBody();
    }
    
    // 토큰 생성
    public static String generateToken(String userName, String key, long expiredTimeMs) {
        Claims claims = Jwts.claims();
        claims.put("userName", userName);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expiredTimeMs))
                .signWith(getKey(key), SignatureAlgorithm.HS256)  // HS256 알고리즘 사용
                .compact();

    }
    
    // key 반환
    private static Key getKey(String key) {
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);

        return Keys.hmacShaKeyFor(keyBytes);
    }
}

위가 0.11.5 버전인데 찾아보니 0.12.5 버전이 있어서 그 버전으로 새로운 프로젝트를 만들고 싶어서 똑같이 사용을 해봤으나 deprecated라는 문구가 많이 생겼습니다.

 

그래서 찾아보니 

package com.doubles.selfstudy.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

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

public class JwtTokenUtils {

    // userId 반환
    public static String getUserId(String token, String key) {
        return extractClaims(token, key).get("userId", String.class);
    }

    // 토큰 종료 시간
    public static boolean isExpired(String token, String key) {
        Date expiredDate = extractClaims(token, key).getExpiration();

        return expiredDate.before(new Date());
    }
    
    // claim 추출
    private static Claims extractClaims(String token, String key) {
        return Jwts
                .parser() // JWT 파서 객체 생성 (JWT에서 헤더, 페이로드, 서명 추출에 사용하기 위해)
                .verifyWith(getKey(key)) // 서명 검증에 사용할 키 설정
                .build() // 파서 빌드
                .parseSignedClaims(token) // 토큰을 위에 서명 검증할 키를 통해 파싱
                .getPayload(); // 클레임 추출
    }

    // 토큰 생성
    public static String createJwtToken(String userId, String key, long expiredTimeMs) {
        return Jwts.builder()
                .claim("userId", userId)
                .issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + expiredTimeMs))
                .signWith(getKey(key))
                .compact();
    }
    
    // 서명 키 생성 메소드
    private static SecretKey getKey(String key) {
        return new SecretKeySpec(
                key.getBytes(StandardCharsets.UTF_8),
                Jwts.SIG.HS256.key().build().getAlgorithm() // HS256 사용
        );
    }
}

변경점을 정리하자면

  • claims에 들어가는 값의 타입이 Jwts.claims()에서 Map으로 변경되었습니다. 하지만 1개만 사용하므로 claim으로 바꾸었습니다.
  • singWith의 입력 값이 알고리즘과 같이 받았지만 새로운 버전에는 SecretKey를 받게 되어 SecretKey 생성 시 알고리즘을 미리 받아서 생성하여 전달하도록 했습니다.
  • claim 추출 메소드에서 paserBuilder가 paser로 변경되었습니다.
  • setSigningKey이 verifyWith가 되었습니다.
  • parseClaimsJws이 parseSignedClaims이 되었습니다.

위와 같이 변경하고 postman을 통해서 create 테스트를 해보니 성공하였습니다.

 

❗ 프로잭트 진행하면서 문제가 생기면 다시 수정할 수도 있습니다.