스프링부트 - JWT(Json Web Token)이란?

2025. 5. 11. 20:05·Spring
728x90
반응형
SMALL

JWT(Json Web Token)이란?

  • 인증 정보를 Json 형태로 담아 서버-클라이언트 간 안전하게 전달하기 위한 토큰이다.
  • 서버에서 발급하고 클라이언트에 저장
  • 토큰 자체에 사용자의 모든 정보를 포함하는 것이 가능하다.
  • 사용자의 정보가 변경되면 토큰을 재발급 받아야된다.
  • JSON 데이터를 Base64 인코딩을 통해 직렬화

JWT 구조

.(dot)을 기준으로 헤더 내용 서명이 JWT토큰 하나를 이룬다.

만약에 토큰이 완성되면 다음과 같은 형식을 따른다.


Base64

ASCII 중 제어 문자와 일부 특수 문자를 제외한 64개의 안전한 문자이다.


Header

typ: 토큰 타입"JWT"

alg(알고리즘): SHA-256, SHA-384, SHA-512

                       ECDSA(ES), HMAC(HS), RSASSA-PSS(PS), RSASSA-PKCS(RS)

헤더 JSON에는 다음과 같은 데이터가 담긴다고 볼 수 있다.

그럼 이 헤더를 HS256으로 인코딩을 시키면 

다음과 같은 값이 나올 수 있다.

 

Payload(Data)

  • 정보 중 한조각 claim(key)이라고 부르면, key-value 쌍으로 구성된다.
  • 등록(registered), 공개(public), 비공개(private) claim으로 나누지만 
    임의의 데이터를 자유롭게 사용하기 위해서 비공개 claim을 많이 사용
  • 어떤 이름으로 JWT를 만들었냐에 따라서 꺼낼 때 내용이 달라질 수 있다.

위의 JSON데이터가 인코딩을 거치면 다음과 같이 나온다.

 

Signature

  • 헤더의 base63 인코딩 값과 Payload base64 인코딩 값을 합친 후 서명키로 다시 해싱한 값
  • 보통 secret키가 쓰여지는데(43자 이상) 보통 랜덤으로 키를 만들어서 넣어준다.

JWT를 사용하려면 의존 라이브러리 추가를 해줘야한다.

            <dependency>
                <groupId>nz.net.ultraq.thymeleaf</groupId>
                <artifactId>thymeleaf-layout-dialect</artifactId>
    </dependency>
    <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-api</artifactId>
                <version>0.11.5</version>
    </dependency>
    <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
            <scope>runtime</scope>
    </dependency>

다음과 같이 의존성을 줘야된다.

 

JwtTests.java

@Test
    void createJwt() {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        byte[] secretKeyBytes = DatatypeConverter.parseBase64Binary(
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr");
        Key signingKey = new SecretKeySpec(secretKeyBytes, signatureAlgorithm.getJcaName());
        JwtBuilder builder = Jwts.builder()
                // Header
                .setHeaderParam("typ", "JWT")
                // Payload - Registered Claim
                .setSubject("제목").setIssuer("ggoreb.com").setAudience("service user")
                // Payload - Secret Claim
                .claim("username", "ggoreb").claim("password", 1234).claim("hasPermission", "ADMIN")
                // Signature
                .signWith(signingKey, signatureAlgorithm);
        long now = System.currentTimeMillis();
        builder.setExpiration(new Date(now + 3600000)); // 1시간 뒤 토큰 유효기간 만료
        String token = builder.compact();
        log.info("jwt {}", token);
    }

해당 코드는 JWT를 생성하는 테스트 코드이다.

서명에 사용할 알고리즘과 비밀 키(Base64인코딩 된 문자열)를 설정한다.

JwtBuilder로 Header, Payload, signature를 설정해준다.

setExpiration메서드로 1시간 뒤 토큰 유효기간을 만료시킨다.

 

그럼 이 테스트 코드를 실행시켜보면

다음과 같이 JWT토큰이 생성되는 것을 확인 할 수 있다.

@Test
    void getDataFromJwt() {
        byte[] secretKeyBytes = DatatypeConverter.parseBase64Binary(
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr");
        String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLsoJzrqqkiLCJpc3MiOiJnZ29yZWIuY29tIiwiYXVkIjoic2VydmljZSB1c2VyIiwidXNlcm5hbWUiOiJnZ29yZWIiLCJwYXNzd29yZCI6MTIzNCwiaGFzUGVybWlzc2lvbiI6IkFETUlOIiwiZXhwIjoxNzQ2OTY0MjQ2fQ.-MMoyH_lXkCq2KtoBQuVqs-UijLONsZ8n7pV3Ctpg7c";
        JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(secretKeyBytes).build();
        JwsHeader<?> header = jwtParser.parseClaimsJws(jwt).getHeader();
        String algorithm = header.getAlgorithm();
        log.info("Algorithm {}", algorithm);
        String type = header.getType();
        log.info("Type {}", type);
        Claims claims = jwtParser.parseClaimsJws(jwt).getBody();
        log.info("Subject {}", claims.getSubject());
        log.info("Issuer {}", claims.getIssuer());
        log.info("Audience {}", claims.getAudience());
        log.info("claim {}", claims.get("username"));
        log.info("claim {}", claims.get("password"));
        log.info("claim {}", claims.get("hasPermission"));
    }

Jwt확인하는 테스트 코드를 작성해보자

그럼 다음과 같이 Jwt의 상세 내용에 대해서 나온다.

 

그럼 1시간이 아니라 5초쯤으로 토큰 유효기간을 설정해서 확인하는 테스트코드를 작성해보자

@Test
    void getDataFromJwt() {
        byte[] secretKeyBytes = DatatypeConverter.parseBase64Binary(
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr");
        String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLsoJzrqqkiLCJpc3MiOiJnZ29yZWIuY29tIiwiYXVkIjoic2VydmljZSB1c2VyIiwidXNlcm5hbWUiOiJnZ29yZWIiLCJwYXNzd29yZCI6MTIzNCwiaGFzUGVybWlzc2lvbiI6IkFETUlOIiwiZXhwIjoxNzQ2OTYxMzUxfQ.KixtgVF1kG6-UUEpnCQLaUiwrq6pTucWw-KFDWH8dcs";
        JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(secretKeyBytes).build();
        JwsHeader<?> header = jwtParser.parseClaimsJws(jwt).getHeader();
        String algorithm = header.getAlgorithm();
        log.info("Algorithm {}", algorithm);
        String type = header.getType();
        log.info("Type {}", type);
        Claims claims = jwtParser.parseClaimsJws(jwt).getBody();
        log.info("Subject {}", claims.getSubject());
        log.info("Issuer {}", claims.getIssuer());
        log.info("Audience {}", claims.getAudience());
        log.info("claim {}", claims.get("username"));
        log.info("claim {}", claims.get("password"));
        log.info("claim {}", claims.get("hasPermission"));
    }

5초로 생성하고 새롭게 발급받은 JWT를 확인하는 테스트를 실행해보자

다음과 같이 ExpriedJwtException이 뜨는것을 볼 수 있다.

ExpriedJwtException은 JWT가 만료되었을 때 발생하는 예외이다.

JWT토큰 유효기간을 5초로 설정했으니 당연한 얘기이다.

따라서 JWT의 유효기간을 적절하게 설정하는 것이 좋다.

728x90
반응형
LIST

'Spring' 카테고리의 다른 글

스프링부트 - 타임리프(Thymeleaf)  (1) 2025.05.13
스프링부트 - 스프링 시큐리티  (0) 2025.05.11
스프링부트 - 파일 업로드  (0) 2025.05.10
스프링부트 - 필터(FilterRegistrationBean)  (0) 2025.05.10
[스프링부트] - 인터셉터(interceptor)  (1) 2025.05.09
'Spring' 카테고리의 다른 글
  • 스프링부트 - 타임리프(Thymeleaf)
  • 스프링부트 - 스프링 시큐리티
  • 스프링부트 - 파일 업로드
  • 스프링부트 - 필터(FilterRegistrationBean)
코린이 파닥거리기
코린이 파닥거리기
    반응형
    250x250
  • 코린이 파닥거리기
    코린이 파닥거리기의 블로그
    코린이 파닥거리기
  • 전체
    오늘
    어제
    • 분류 전체보기 (124) N
      • 백준[파이썬] (53) N
      • Spring (31)
      • CS (1)
      • 자바 (4)
      • 백준[자바] (20)
      • 프로그래머스 (5)
      • 토이프로젝트 (1)
      • SWEA (2)
      • MSA (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자바
    spring
    스프링부트
    누적합
    MSA
    재귀
    JWT
    코딩테스트
    백준
    프로그래머스
    스프링
    SpringBoot
    SWEA
    스프링 부트와 AWS로 혼자 구현하는 웹 서비스
    컨테이너
    Java
    db
    파이썬
    테스트코드
    JPA
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코린이 파닥거리기
스프링부트 - JWT(Json Web Token)이란?
상단으로

티스토리툴바