-
FastAPI 시리즈 12화 - JWT 기반 인증 시스템 완성: 토큰 구조와 보안 처리 심화기술과 산업/언어 및 프레임워크 2025. 5. 30. 01:20728x90
FastAPI에서 JWT(Json Web Token)의 구조, 만료 처리, 리프레시 토큰 전략, 서명 보안 방식 등을 실전 중심으로 다룹니다. 인증 시스템을 안전하게 완성하는 방법을 소개합니다.
왜 JWT 구조를 이해해야 하는가?
JWT(Json Web Token)는 다음과 같은 구조로 구성됩니다:
HEADER.PAYLOAD.SIGNATURE
파트설명
Header 알고리즘 및 타입 (alg, typ) Payload 사용자 데이터 (sub, exp, role 등) Signature 서버 비밀키로 서명된 무결성 보장 부분 ✅ JWT는 읽을 수 있지만 조작할 수 없어야 합니다.
따라서 서명(Signature)을 검증하지 않으면, 누구나 위조된 토큰을 만들 수 있게 됩니다.
1. JWT 유효성 검증 강화
from jose import jwt, JWTError from fastapi import HTTPException def verify_token(token: str): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) return payload except JWTError: raise HTTPException(status_code=401, detail="Invalid token")
- jwt.decode()는 signature 검증 + 만료 확인까지 자동 수행
- JWTError로 모든 오류 포착 가능
- signature가 일치하지 않으면 인증 실패
2. 토큰 만료 시간 처리 (exp)
from datetime import datetime, timedelta def create_access_token(data: dict, expires_delta: timedelta = None): to_encode = data.copy() expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15)) to_encode.update({"exp": expire}) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
- exp 필드는 ISO UTC 기준으로 입력
- Swagger에서 만료된 토큰은 즉시 401 반환됨
3. 리프레시 토큰 전략 설계
📌 왜 필요한가?
- 액세스 토큰은 수명이 짧아야 보안에 유리 (15~30분)
- 매번 로그인할 수 없기 때문에 장기 보관용 리프레시 토큰이 필요
📌 리프레시 토큰 흐름
1. 로그인 성공 → access_token + refresh_token 발급 2. access_token 만료 시 → refresh_token으로 재발급 요청 3. refresh_token은 DB나 Redis에서 상태 관리
4. 리프레시 토큰 발급 예제
def create_refresh_token(data: dict): expire = datetime.utcnow() + timedelta(days=7) data.update({"exp": expire}) return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
@app.post("/token/refresh") def refresh_token(refresh_token: str): try: payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=[ALGORITHM]) username = payload.get("sub") # 추가 검증: DB에서 refresh_token 유효성 확인 필요 new_access = create_access_token({"sub": username}) return {"access_token": new_access} except JWTError: raise HTTPException(status_code=401, detail="Invalid refresh token")
5. 실무 보안 강화 포인트
항목설명
비밀번호 해싱 bcrypt 활용 (pip install passlib[bcrypt]) 토큰 블랙리스트 로그아웃 시 refresh_token 무효화 (DB나 Redis 활용) HTTPS 적용 토큰 유출 방지를 위해 항상 TLS 사용 secure, httponly 쿠키 토큰을 쿠키에 저장 시 필수 설정 사용자 역할(Role) 기반 제어 JWT Payload에 role 포함 후 접근 제어 적용
6. 사용자 권한(Role) 기반 API 접근 제어
def get_admin_user(token: str = Depends(oauth2_scheme)): payload = verify_token(token) if payload.get("role") != "admin": raise HTTPException(status_code=403, detail="Admins only") return payload @app.get("/admin/dashboard") def read_admin_dashboard(user=Depends(get_admin_user)): return {"message": f"Welcome {user['sub']}, to the admin dashboard"}
- JWT에 사용자 role 정보를 포함시키고
- 인증 함수에서 권한 확인 로직을 분리
FastAPI 인증 시스템을 진짜 서비스 수준으로 완성하려면
항목적용 방법
JWT 발급 sub, exp 포함 후 서명 토큰 만료 timedelta 기반 설정 리프레시 토큰 별도 토큰 발급 + 상태 관리 사용자 권한 제어 JWT에 role 필드 포함 보안 강화 HTTPS, bcrypt, 토큰 저장소, 쿠키 옵션 등 적용 필요 FastAPI는 인증을 “쉽게 시작할 수 있으면서도, 깊이 있게 확장 가능한 구조”로 설계되어 있습니다.
이제 로그인 기능을 넘어서 서비스 전반의 인증/보안 흐름을 스스로 구성할 수 있는 수준까지 도달한 것입니다.
다음 글 예고
FastAPI 시리즈 13화 - 사용자 권한(Role) 관리와 종속성 적용 방법
에서는 사용자 계층별 접근 제어를 어떻게 분리하고, Depends를 활용해 권한 시스템을 구현하는지를 설명합니다.
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
Spring Boot 고급 시리즈 1화 – Spring Boot의 아키텍처 재조명: 왜 우리는 Spring Boot를 선택하는가 (0) 2025.05.30 Spring Boot 시리즈 40편 – 실무에서의 Spring Boot CI/CD 구축 전략 (1) 2025.05.30 Spring Boot 시리즈 38편 – Spring Boot에서 분산 트레이싱(Distributed Tracing) 적용하기 (1) 2025.05.29 Spring Boot 시리즈 37편 – 실시간 기능을 위한 WebSocket 연동 전략 (0) 2025.05.29 Spring Framework 시리즈 10화 – 실무 예제: 간단한 DI 기반 계산기 시스템 구현 (0) 2025.05.29