JWT(Json Web Token)?

mangez_js·2024년 12월 2일

Study

목록 보기
21/47

JWT

header, payload, signature로 구성되어 있으며 header는 signature를 해싱하기 위한 알고리즘 정보가 담겨있고 payload는 실제로 사용될 데이터들이 담겨 있습니다.
signature는 토큰의 유효성 검증을 위한 문자열로 이 문자열을 통해 이 토큰이 유효한 토큰인지 검증 가능합니다.
JWT는 인터페이스이고 그 구현체인 JWS, JWE가 존재합니다.

특징

  1. 자가 포함
  • 토큰에 필요한 모든 정보가 포함되어 있으므로, 서버가 별도의 세션 저장소를 유지할 필요가 없습니다.
  1. 무결성 보장
  • 서명을 통해 토큰이 변조되지 않았는지 확인할 수 있습니다.
  1. Base64Url 인코딩
  • 사람이 읽을 수 있는 JSON 데이터를 Base64Url로 인코딩하여 전송하므로 디코딩이 가능합니다. 하지만 서명 키는 비공개로 유지됩니다.
  1. 무상태
  • 서버는 상태를 유지하지 않고 클라이언트가 JWT를 전달하여 인증 과정을 수행합니다.

장점

  • 확장성
    ∘ 서버 확장 시 세션 정보를 공유할 필요가 없음
  • 효율성
    ∘ 클라이언트-서버 간 HTTP 요청에 추가적인 인증 요청이 필요 없음
  • 무상태성
    ∘ 서버는 상태를 유지하지 않아도 됨

단점

  • 취소 불가
    ∘ 발급된 JWT는 만료되기 전까지 취소할 수 없습니다.(추가 로직 필요)
  • 페이로드 노출
    ∘ 인코딩된 정볼르 쉽게 디코딩할 수 있으므로 민감 정보를 포함하면 안 됨
  • 토큰 크기
    ∘ JWT 크기가 커질수록 네트워크 부담 증가

설정

  • JwtProperties
@Data
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties{
	private RSAPublicKey accessPublicKey;
    private RSAPrivateKey accessPrivateKey;
    private Long accessTokenValidityInSeconds;
}
  • JwtConfig(JWT 의존성 주입 설정파일)
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(JwtProperties.class)
public class JwtConfig{
 @Bean(name = "accessJwtDecoder")
    public JwtDecoder accessJwtDecoder(JwtProperties jwtProperties) {
        return NimbusJwtDecoder.withPublicKey(jwtProperties.getAccessPublicKey()).build();
    }

    @Bean(name = "accessJwtEncoder")
    public JwtEncoder accessJwtEncoder(JwtProperties jwtProperties) {
        JWK jwk = new RSAKey.Builder(jwtProperties.getAccessPublicKey())
                .privateKey(jwtProperties.getAccessPrivateKey())
                .build();
        JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
        return new NimbusJwtEncoder(jwks);
    }

    
    @Bean(name = "accessTokenProvider")
    public AccessTokenProvider accessTokenProvider(JwtEncoder accessJwtEncoder,
                                                   JwtProperties jwtProperties) {
        return new AccessTokenProvider(accessJwtEncoder, jwtProperties.getAccessTokenValidityInSeconds());
    }
}

JwtConfig는 JWT 설정 파일로 AccessTokenProvider에 의존성을 주입하고 빈을 생성하는 역할을 수행합니다.
JWT 토큰 인코딩, 디코딩의 책임을 가지는 JwtDecoder 빈, JwtEncoder 빈도 이쪽 설정파일에서 생성합니다.

  • AccessTokenProvider
public final class AccessTokenProvider {

    private final JwtEncoder jwtEncoder;
    private final long tokenValidityInSeconds;
    private static final String AUTHORITIES_KEY = "scp"; // spring security 기본값 (scope)

    public AccessTokenProvider(JwtEncoder jwtEncoder, long tokenValidityInSeconds) {
        this.jwtEncoder = jwtEncoder;
        this.tokenValidityInSeconds = tokenValidityInSeconds;
    }

    // 토큰 생성
    public String createToken(String username, Set<String> authorities) {
        String strAuthorities = String.join(" ", authorities);

        Instant now = Instant.now();

        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer("self")
                .issuedAt(now)
                .expiresAt(now.plusSeconds(this.tokenValidityInSeconds))
                .subject(username)
                .claim(AUTHORITIES_KEY, strAuthorities)
                .build();
        return jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    }
}

TokenProvider를 상속받으며 아이디, 비밀번호를 이용해 토큰을 생성하는 역할을 수행합니다.

0개의 댓글