#

1.JWT 설정 파일 생성

1. Security 폴더에 JWT제공 파일 생성

2. factory Annotation으로 값 설정하기 기본적으로 application.yml의 환경변수를 받아서 사용할것

token:
  secret-key: "SECRET"
  refresh-secret-key: "REFRESH_SECRET"
  token-time: 300
  refresh-token-time: 1000
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class JWTProvider  {

    private static String secretKey;
    private static String refreshSecretKey;
    private static long tokenTimeForMinute;
    private static long refreshTokenTimeForMinute;
    // 경로를 맞추지 않으면 bean 주입이 실패했다는 오류가 발생한다
    @Value("${token.secret-key}")    // factory.annotation의 value를 사용해서 환경변수 값 가져오기
    public void setSecretKey(String secretKey) {
        JWTProvider.secretKey = secretKey;
    }
    @Value("${token.refresh-secret-key}")
    public void setRefreshSecretKey(String refreshSecretKey) {
        JWTProvider.refreshSecretKey = refreshSecretKey;
    }
    @Value("${token.token-time}")
    public void setTokenTime(long tokenTime)  {
        JWTProvider.tokenTimeForMinute = tokenTime;
    }
    @Value("${token.refresh-token-time}")
    public void setRefreshTokenTime(long refreshTokenTime) {
        JWTProvider.refreshTokenTimeForMinute = refreshTokenTime;
    }
}

3. Token의 Payload에 값 주입하기

  • JWT 생성 메서드 만들기

        public static String createToken(String username){
            return JWT.create()
                    .withSubject(username)
                    .withIssuedAt(new Date())
                    .withExpiresAt(new Date(System.currentTimeMillis() * 1000)) // 원하는대로 설정
                    .sign(Algorithm.HMAC256(secretKey));
        }
    
    1. 상수로 만들어서 시간 설정하기
    • 상수 파일 생성
    @NoArgsConstructor
    public class Constants {
    public static final long ON_MINUTE_TO_MILLIS = 60 * 1000L;
    }
    
    • JWT 생성 메서드에 적용
        public static String createToken(String username){
            return JWT.create()
                    .withSubject(username)
                    .withIssuedAt(new Date())
                    .withExpiresAt(new Date(System.currentTimeMillis() * Constants.ON_MINUTE_TO_MILLISN)
                    .sign(Algorithm.HMAC256(secretKey));
        }
    
  • JWTCreator.class 접은글로 넣기
 public Builder withKeyId(String keyId) {
            this.headerClaims.put("kid", keyId);
            return this;
        }

        public Builder withIssuer(String issuer) {
            this.addClaim("iss", issuer);
            return this;
        }

        public Builder withSubject(String subject) {
            this.addClaim("sub", subject);
            return this;
        }

        public Builder withAudience(String... audience) {
            this.addClaim("aud", audience);
            return this;
        }

        public Builder withExpiresAt(Date expiresAt) {
            this.addClaim("exp", expiresAt);
            return this;
        }

        public Builder withNotBefore(Date notBefore) {
            this.addClaim("nbf", notBefore);
            return this;
        }

        public Builder withIssuedAt(Date issuedAt) {
            this.addClaim("iat", issuedAt);
            return this;
        }

        public Builder withJWTId(String jwtId) {
            this.addClaim("jti", jwtId);
            return this;
        }

4. JWT 인증 및 에러 헨들링

// Custom Error Code
ACCESS_TOKEN_IS_NOT_EXPIRED(-200, "token is not expired"),

TOKEN_IS_INVALID(-201, "token is invalid"),

TOKEN_IS_EXPIRED(-202, "token is expired");
// 리프레시용 함수
public static DecodedJWT checkTokenFroRefresh(String token){
    try{

        DecodedJWT decoded = JWT.require(Algorithm.HMAC256(secretKey)).build().verify(token);
        log.error("token must be expired: {}", decoded.getSubject());
        throw new CustomException(ErrorCode.ACCESS_TOKEN_IS_NOT_EXPIRED);

    }catch(AlgorithmMismatchException | SignatureVerificationException | InvalidClaimException e){

        throw new CustomException(ErrorCode.TOKEN_IS_INVALID);

    }catch(TokenExpiredException e){

        return JWT.decode(token);

    }
}

public static DecodedJWT decodedAccessToken(String token){
    return decodeTokenAfterVerify(token, secretKey);
}

public static DecodedJWT decodedRefreshToken(String token){
    return decodeTokenAfterVerify(token, refreshSecretKey);
}

// 정상적으로 인증완료시
private static DecodedJWT decodeTokenAfterVerify(String token, String key){
    try{
        return JWT.require(Algorithm.HMAC256(key)).build().verify(token);
    }catch(AlgorithmMismatchException | SignatureVerificationException | InvalidClaimException e){
        throw new CustomException(ErrorCode.TOKEN_IS_INVALID);
    }catch(TokenExpiredException e){
        throw new CustomException(ErrorCode.TOKEN_IS_EXPIRED);
    }
}


// JWT 디코딩
public static DecodedJWT decodedJWT(String token){
    return JWT.decode(token);
}

5. HTTP Protocol 로직 처리

댓글남기기