JWT 자체는 인증/인가와 관련이 없다 → 정보를 안전하게 전송하기 위한 방법 중 하나이다.
JWT는 3가지 부분으로 구성
{
"alg":"HS256",
"typ": "JWT"
}애플리케이션에서 사용할 수 있는 클레임이다.
사용자 정의 정보를 포함할 수 있는 클레임으로, 서버와 클라이언트 간의 임의적인 정보를 주고받을 수 있다.
{
"id": "user123",
"name": "John Doe",
"company" : "test",
"admin": true
}
1️⃣ 생성
2️⃣ 전송
3️⃣ 검증
JWT(JSON Web Token)을 생성하고 검증하는 유틸리티 클래스
jwt:
secretKey: 12345678901234567890123456789012
refreshKey: 12345678901234567890123456789012
@Component
@Slf4j
public class JwtTokenizer {
private final byte[] accessSecret;
private final byte[] refreshSecret;
//토큰 만료 시간이 달라지면 안되기 때문에 static으로 사용해야 한다.
public static final Long ACCESS_TOKEN_EXPIRE_COUNT = 5 * 60 * 60 * 1000L;
// Access Token 유효기간: 5시간 (5시간 * 60분 * 60초 * 1000ms)
public static final Long REFRESH_TOKEN_EXPIRE_COUNT = 24 * 60 * 60 * 1000L;
// Refresh Token 유효기간: 1일 (24시간 * 60분 * 60초 * 1000ms)
public JwtTokenizer(@Value("${jwt.secretKey}") String accessSecret, @Value("${jwt.refreshKey}") String refreshSecret) {
this.accessSecret = accessSecret.getBytes(StandardCharsets.UTF_8);
this.refreshSecret = refreshSecret.getBytes(StandardCharsets.UTF_8);
}
private static Key getSigningKey(byte[] secretKey){
return Keys.hmacShaKeyFor(secretKey);
}
//accessToken 생성
public String createToken(Long id, String email,byte[] secretKey,Long expire){
//이 토큰의 주인이 누구인지 나타내는 클레임
//고유한 식별자 값 저장
Claims claims = Jwts.claims().setSubject(email);
claims.put("userId",id);
claims.put("email",email);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(new Date())
.setExpiration(new Date(new Date().getTime()+expire))
.signWith(getSigningKey(secretKey))
.compact();
}
Jwts.builder()setClaimssetIssuedAtsetExpirationsignWith(getSigningKey(secretKey))compact()결과로 아래 같은 jwt 토큰 문자열이 생성
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI.. . .~
//access token 생성
public String createAccessToken(Long id, String email){
return createToken(id, email, accessSecret,ACCESS_TOKEN_EXPIRE_COUNT);
}
//refresh token
public String refreshAccessToken(Long id, String email){
return createToken(id, email, refreshSecret, REFRESH_TOKEN_EXPIRE_COUNT);
}
//받은 토큰에서 데이터 받는 메서드
public Claims parseToken(String token, byte[] secretKey){
return Jwts.parserBuilder()
.setSigningKey(getSigningKey(secretKey))
.build()
.parseClaimsJws(token)
.getBody();
}
Jwts.parserBuilder()setSigningKey(getSigningKey(secretKey))build()parseClaimsJws(token)getBody()public Long getUserIdFromToken(String token) {
String[] tokenArr = token.split(" ");
token = tokenArr[1];
Claims claims = parseToken(token, accessSecret);
return Long.valueOf((Integer)claims.get("userId"));
}
public Claims parseAccessToken(String accessToken){
return parseToken(accessToken, accessSecret);
}
public Claims parseRefreshToken(String refreshToken){
return parseToken(refreshToken,accessSecret);
}
public static void main(String[] args) {
// 토큰 생성을 위한 JwtTokenizer 인스턴스 생성
JwtTokenizer jwtTokenizer = new JwtTokenizer(
"12345678901234567890123456789012"
,
"12345678901234567890123456789012");
// AccessToken 생성 예시
String accessToken = jwtTokenizer.createAccessToken(
1L,
"test@example.com");
// AccessToken 파싱 예시
Claims accessTokenClaims = jwtTokenizer.parseAccessToken(accessToken);
log.info("Access Token Claims: {}"
, accessTokenClaims);
// RefreshToken 파싱 예시
Claims refreshTokenClaims = jwtTokenizer.parseRefreshToken(refreshToken);
log.info("Refresh Token Claims: {}"
, refreshTokenClaims);
}