Skip to content

Commit

Permalink
feat: JWT 토큰 검증, 발급, 파기, 파싱 기능 구현 #8
Browse files Browse the repository at this point in the history
  • Loading branch information
PgmJun committed Jan 19, 2024
1 parent cd23cc4 commit 6de209a
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.nice.petudio.global.auth.jwt;

import com.nice.petudio.global.util.jwt.JwtKey;
import com.nice.petudio.global.util.redis.RedisKey;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import io.jsonwebtoken.security.Keys;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import javax.crypto.SecretKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class JwtTokenService {

private final RedisTemplate<String, Object> redisTemplate;
private final SecretKey secretKey;
private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 30; // 30분
private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 30L; // 30일
private static final long EXPIRED_TIME = 1;

public JwtTokenService(@Value("${jwt.secret}") String secretKey, RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
this.secretKey = Keys.hmacShaKeyFor(keyBytes);
}


public List<String> createToken(Long memberId) {
long now = (new Date()).getTime();
Date accessTokenExpiryTime = new Date(now + ACCESS_TOKEN_EXPIRE_TIME);
Date refreshTokenExpiryTime = new Date(now + REFRESH_TOKEN_EXPIRE_TIME);

// Access Token 생성
String accessToken = Jwts.builder()
.claim(JwtKey.MEMBER_ID.getKey(), memberId)
.setExpiration(accessTokenExpiryTime)
.signWith(secretKey, SignatureAlgorithm.HS512)
.compact();

String refreshToken = Jwts.builder()
.setExpiration(refreshTokenExpiryTime)
.signWith(secretKey, SignatureAlgorithm.HS512)
.compact();

redisTemplate.opsForValue()
.set(RedisKey.REFRESH_TOKEN.getKey() + memberId, refreshToken, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);

return List.of(accessToken, refreshToken);
}

public void expireRefreshToken(Long memberId) {
redisTemplate.opsForValue()
.set(RedisKey.REFRESH_TOKEN.getKey() + memberId, "", EXPIRED_TIME, TimeUnit.MILLISECONDS);
}

public Optional<Long> parseMemberId(String accessToken) {
return Optional.ofNullable(parseClaims(accessToken).get(JwtKey.MEMBER_ID.getKey(), Long.class));
}

private Claims parseClaims(String token) {
try {
return Jwts.parserBuilder().setSigningKey(secretKey).build()
.parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e) {
return e.getClaims();
}
}

public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token);
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException | DecodingException e) {
log.warn("Invalid JWT token ", e);
} catch (ExpiredJwtException e) {
log.error("Expired JWT token", e);
} catch (UnsupportedJwtException e) {
log.error("Unsupported JWT token", e);
} catch (IllegalArgumentException e) {
log.error("JWT claims is empty.", e);
} catch (Exception e) {
log.error("Unhandled JWT exception", e);
}
return false;
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/nice/petudio/global/util/jwt/JwtKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.nice.petudio.global.util.jwt;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum JwtKey {
MEMBER_ID("memberId");

private final String key;
}
12 changes: 12 additions & 0 deletions src/main/java/com/nice/petudio/global/util/redis/RedisKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.nice.petudio.global.util.redis;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Getter
public enum RedisKey {
REFRESH_TOKEN("RT:");

private final String key;
}

0 comments on commit 6de209a

Please sign in to comment.