6.2 JWT 이해

약 8분

본문 듣기
읽기 설정

글자 크기

줄 간격

글꼴

6.2 JWT 이해

JWT(Jason Web Token)란?

JWT는 두 개체 간에 정보를 안전하게 전송하기 위해 사용되는 JSON 형식의 웹 토큰입니다. 이 토큰은 클라이언트와 서버 간의 인증 및 정보 교환을 간편하게 해줍니다. JWT는 세 부분으로 구성되어 있으며, 각각 헤더(Header), 페이로드(Payload), 서명(Signature)으로 나누어집니다.

JWT의 구조

JWT는 다음과 같은 형식으로 이루어집니다:

<헤더>.<페이로드>.<서명>
  1. 헤더(Header): 토큰의 유형과 서명 알고리즘을 지정합니다.
    예: { "alg": "HS256", "typ": "JWT" }
  2. 페이로드(Payload): 실제로 전달할 데이터가 담깁니다. 사용자 아이디 및 역할 같은 정보를 포함할 수 있습니다.
    예: { "sub": "1234567890", "name": "John Doe", "admin": true }
  3. 서명(Signature): 토큰의 신뢰성을 확인하기 위해 사용됩니다. 이 부분은 헤더와 페이로드를 결합하고 비밀 키로 서명하여 생성됩니다.

JWT 사용 예시

예를 들어, 사용자가 로그인하면 서버는 사용자 정보를 기반으로 JWT를 생성하여 클라이언트에 전달합니다. 클라이언트는 이 토큰을 저장하고 이후 요청에서 Authorization 헤더에 붙여 서버로 보냅니다. 서버는 이 토큰을 검증하여 사용자의 인증 여부를 판단합니다.

실습: FastAPI를 사용한 JWT 생성 및 검증

이번 실습에서는 FastAPI를 활용하여 JWT를 생성하고 사용하는 간단한 API를 만들어 봅시다.

환경 설정

FastAPI 및 필요한 라이브러리를 설치합니다:

pip install fastapi uvicorn python-jose[cryptography] passlib[bcrypt]
코드 python
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from jose import JWTError, jwt
from datetime import datetime, timedelta

# 비밀 키 및 알고리즘 설정
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

app = FastAPI()

# OAuth2PasswordBearer 인스턴스 생성
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")

# 사용자 정보 모델
class User(BaseModel):
    username: str

# 인증된 사용자 모델
class Token(BaseModel):
    access_token: str
    token_type: str 

# JWT 생성 함수
def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    if expires_delta:
        expires = datetime.utcnow() + expires_delta
    else:
        expires = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expires})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

@app.post("/token", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    
    # 여기서 사용자 인증을 진행하세요
    if form_data.username != "user" or form_data.password != "password":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={'sub': form_data.username}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/users/me/", response_model=User)
async def read_users_me(token: str = Depends(oauth2_scheme)):
    
    # 토큰 검증 함수
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    return User(username=username)

댓글 0

댓글을 남기려면 로그인하세요.

아직 댓글이 없습니다. 첫 댓글을 남겨보세요.