약 8분
본문 듣기
읽기 설정
글자 크기
줄 간격
글꼴
6.2 JWT 이해
JWT(Jason Web Token)란?
JWT는 두 개체 간에 정보를 안전하게 전송하기 위해 사용되는 JSON 형식의 웹 토큰입니다. 이 토큰은 클라이언트와 서버 간의 인증 및 정보 교환을 간편하게 해줍니다. JWT는 세 부분으로 구성되어 있으며, 각각 헤더(Header), 페이로드(Payload), 서명(Signature)으로 나누어집니다.
JWT의 구조
JWT는 다음과 같은 형식으로 이루어집니다:
<헤더>.<페이로드>.<서명>
- 헤더(Header): 토큰의 유형과 서명 알고리즘을 지정합니다.
예:{ "alg": "HS256", "typ": "JWT" } - 페이로드(Payload): 실제로 전달할 데이터가 담깁니다. 사용자 아이디 및 역할 같은 정보를 포함할 수 있습니다.
예:{ "sub": "1234567890", "name": "John Doe", "admin": true } - 서명(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
아직 댓글이 없습니다. 첫 댓글을 남겨보세요.