JWT

김나영·2023년 6월 28일
0

Spring

목록 보기
19/38

JWT란?

  • JSON 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token 즉, 토큰의 한 종류

  • 일반적으로 쿠키 저장소를 사용하여 JWT를 저장

왜 사용할까?

1. 서버가 1대인 경우

  • Session1 이 모든 Client의 로그인 정보를 소유

2. 서버가 2대 이상인 경우

  • 서버의 대용량 트래픽 처리를 위해 서버 2대 이상 운영이 필요할 수 있음

  • Session 마다 다른 Client 로그인 정보를 가지고 있을 수 있음

    • Session1: Client1, Client2, Client3
    • Session2: Client4
    • Session3: Client5, Client6
  • 만약 Client 1의 로그인 정보를 가지고 있지 않은 Sever2 나 Server3 에 API 요청을 하게되면 문제가 발생?

    • 해결방법

      1) Sticky Session: Client 마다 요청 Server 고정

      2) 세션 저장소 생성하여 모든 세션을 저장

3. 세션 저장소 생성

  • Session storage 가 모든 Client 의 로그인 정보 소유하고 있기 때문에 모든 서버에서 모든 Client의 API 요청을 처리할 수 있음

4. JWT 사용

  • 로그인 정보를 Server 에 저장하지 않고, Client 에 로그인 정보를 JWT 로 암호화하여 저장 → JWT 통해 인증/인가

  • 모든 서버에서 동일한 Secret Key 소유

  • Secret Key 통한 암호화 / 위조 검증 (복호화 시)

장단점

1. 장점

  • 동시 접속자가 많을 때 서버 측 부하 낮춤

  • Client, Sever 가 다른 도메인을 사용할 때

    • 예) 카카오 OAuth2 로그인 시 JWT Token 사용

2. 단점

  • 구현의 복잡도 증가

  • JWT 에 담는 내용이 커질 수록 네트워크 비용 증가 (클라이언트 → 서버)

  • 기 생성된 JWT 를 일부만 만료시킬 방법이 없음

  • Secret key 유출(외부로) 시 JWT 조작 가능

사용 흐름

1. Client가 username, password로 로그인 성공 시

  • 서버에서 " 로그인 정보 " --> JWT로 암호화(Secret Key 사용)

    • ex)
  • 서버에서 직접 쿠키를 생성해 JWT를 담아 Client 응답에 전달

    • JWT 전달 방법은 개발자가 정함

      • 응답 Header에 아래 형태로 JWT 전달
Cookie cookie = new Cookie(AUTHORIZATION_HEADER, token); // Name-Value
cookie.setPath("/");
// Response 객체에 Cookie 추가
res.addCookie(cookie);

  • 브라우저 쿠키 저장소에 자동으로 JWT 저장됨

2. Client에서 JWT 통해 인증 방법

1) 서버에서 API 요청 시마다 쿠키에 포함된 JWT를 찾아서 사용

  • 쿠키를 찾는 코드
// HttpServletRequest 에서 Cookie Value : JWT 가져오기
public String getTokenFromRequest(HttpServletRequest req) {
    Cookie[] cookies = req.getCookies();
    if(cookies != null) {
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(AUTHORIZATION_HEADER)) {
                try {
                    return URLDecoder.decode(cookie.getValue(), "UTF-8"); // Encode 되어 넘어간 Value 다시 Decode
                } catch (UnsupportedEncodingException e) {
                    return null;
                }
            }
        }
    }
    return null;
}
  • 쿠키에 담긴 정보가 여러 개일 수 있기 때문에 그 중 이름이 JWT가 담긴 쿠키의 이름과 동일한지 확인하여 JWT를 가져옴
  • 컨트롤러가 아닌 다른 곳에서 받을 때 위와 같은 로직 필요

2) Server

  • Client가 전달한 JWT 위조 여부 검증(Secret Key 사용)

  • JWT 유효 기간이 지나지 않았는지 검증

    • JWT --> 사용자 정보를 가져와 확인
    • ex) GET / api / products : JWT 보낸 사용자의 관심상품 목록 조회

구조

  • JWT는 누구나 평문으로 복호화 가능

  • Secret Key가 없으면 JWT 수정 불가능

    --> Read Only 데이터

  • HEADER

{
  "alg": "HS256",
  "typ": "JWT"
}
  • PAYLOAD
{
  "sub": "1234567890",
  "username": "카즈하",
  "admin": true
}
  • VERIFY SIGNATURE
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
  • Payload에 실제 유저 정보가 들어가 있고, HEADER와 VERIFY SIGNATURE(JWT를 만들 때 사용했던 Secret Key 필요) 부분은 암호화 관련된 정보 양식이라고 생각하면 됨

0개의 댓글