Deep Dive into JWT: 순수 Python으로 FastAPI 인증 구축
Wenhao Wang
Dev Intern · Leapcell

FastAPI에서 JWT를 사용한 인증 구현
소개
최신 웹 애플리케이션 개발에서 인증은 시스템 보안을 보장하는 데 중요한 부분입니다. JSON Web Token (JWT)은 JSON (RFC 7519)을 기반으로 하는 개방형 표준으로서, 간결성과 보안성으로 인해 분산된 사이트의 싱글 사인온 (SSO) 시나리오에서 널리 사용됩니다. FastAPI는 Python을 기반으로 하는 고성능 웹 프레임워크입니다. 이 기사에서는 주어진 JWT 구현 코드와 함께 FastAPI에서 JWT를 사용하여 인증하는 방법을 소개합니다.
JWT의 기본 사항
JWT란 무엇입니까?
JSON Web Token (JWT)은 네트워크 애플리케이션 환경 간에 클레임을 전송하도록 설계되었습니다. 이는 간결하고 안전하며 분산된 사이트의 싱글 사인온 시나리오에 특히 적합합니다. JWT 클레임은 리소스 서버에서 리소스를 얻기 위해 인증된 사용자 ID 정보를 ID 공급자와 서비스 공급자 간에 전송하는 데 자주 사용되며 비즈니스 로직에 필요한 다른 클레임 정보를 추가할 수도 있습니다. 이 토큰은 직접 인증하거나 암호화할 수 있습니다.
JWT의 구성 요소
JWT는 세 개의 정보 세그먼트로 구성됩니다.
- 헤더: 일반적으로 파일 유형 및 암호화 알고리즘을 선언합니다.
- 페이로드: JSON 형식으로 전송할 데이터를 기록합니다.
- 서명: 확인에 사용되는 서명입니다.
base64UrlEncode 메서드
JWT를 생성할 때 base64UrlEncode
메서드가 서명에 사용됩니다. 이 메서드의 기본 기능은 다음과 같습니다.
- UTF-8로 인코딩된 문자열
s1
을 입력합니다. - base64를 사용하여 문자열
s1
을 인코딩하여 문자열s2
를 얻습니다. s2
의 끝에 등호가 있으면 끝에 있는 모든 등호를 제거합니다.s2
에 더하기 기호 (+
)가 있으면 모든 더하기 기호를 빼기 기호 (-
)로 바꿉니다.s2
에 슬래시 (/
)가 있으면 모든 슬래시를 밑줄 (_
)로 바꿉니다.
다음은 이 메서드를 구현하는 Python 코드입니다.
import hmac import base64 from hashlib import sha256 from urllib import parse as urlp def b64url(str1): if type(str1) == str: return str(base64.b64encode(str1.encode('utf-8')), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_') elif type(str1) == bytes: return str(base64.b64encode(str1), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_') else: raise TypeError("The type of given argument must be string or bytes")
HS256으로 암호화된 JWT 생성
다음은 위의 b64url
함수를 사용하여 HS256으로 암호화된 JWT를 생성하는 코드입니다.
# Enter Your Infomation Here ... header = b64url('{"alg":"HS256","typ":"JWT"}') payload = b64url('{"sub":"1234567890","name":"John Doe","iat":1516239022}') secret = 'happynewyear'.encode('utf-8') # ### sig = b64url(hmac.new( secret, (header + '.' + payload).encode('utf-8'), digestmod=sha256 ).digest()) jwt = header + '.' + payload + '.' + sig print(jwt)
FastAPI에서 JWT 통합
종속성 설치
시작하기 전에 fastapi
와 uvicorn
을 설치해야 합니다. 다음 명령을 사용하여 설치할 수 있습니다.
pip install fastapi uvicorn
구현 단계
1. FastAPI 애플리케이션 만들기
from fastapi import FastAPI, HTTPException, Depends from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials import hmac import base64 from hashlib import sha256 app = FastAPI() # Define the b64url function def b64url(str1): if type(str1) == str: return str(base64.b64encode(str1.encode('utf-8')), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_') elif type(str1) == bytes: return str(base64.b64encode(str1), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_') else: raise TypeError("The type of given argument must be string or bytes") # Secret key SECRET_KEY = 'happynewyear'.encode('utf-8') # Function to generate JWT def generate_jwt(): header = b64url('{"alg":"HS256","typ":"JWT"}') payload = b64url('{"sub":"1234567890","name":"John Doe","iat":1516239022}') sig = b64url(hmac.new( SECRET_KEY, (header + '.' + payload).encode('utf-8'), digestmod=sha256 ).digest()) return header + '.' + payload + '.' + sig # Function to verify JWT def verify_jwt(token: str): parts = token.split('.') if len(parts) != 3: return False header, payload, received_sig = parts new_sig = b64url(hmac.new( SECRET_KEY, (header + '.' + payload).encode('utf-8'), digestmod=sha256 ).digest()) return new_sig == received_sig # Define the JWT verification dependency class JWTBearer(HTTPBearer): def __init__(self, auto_error: bool = True): super(JWTBearer, self).__init__(auto_error=auto_error) async def __call__(self, request): credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request) if credentials: if not credentials.scheme == "Bearer": raise HTTPException(status_code=401, detail="Invalid authentication scheme.") if not verify_jwt(credentials.credentials): raise HTTPException(status_code=401, detail="Invalid or expired token.") return credentials.credentials else: raise HTTPException(status_code=401, detail="Invalid authorization code.")
2. 로그인 인터페이스 만들기
# Simulated login interface @app.post("/login") def login(): token = generate_jwt() return {"access_token": token, "token_type": "bearer"}
3. 보호된 인터페이스 만들기
# Protected interface @app.get("/protected", dependencies=[Depends(JWTBearer())]) def protected_route(): return {"message": "This is a protected route."}
애플리케이션 실행
위의 코드를 main.py
로 저장한 다음 터미널에서 다음 명령을 실행하여 애플리케이션을 시작합니다.
uvicorn main:app --reload
인터페이스 테스트
- 로그인 인터페이스:
curl
또는 Postman과 같은 도구를 사용하여http://localhost:8000/login
에 POST 요청을 보내면 JWT가 반환됩니다.
curl -X POST http://localhost:8000/login
- 보호된 인터페이스: 반환된 JWT를 사용하여
http://localhost:8000/protected
에 GET 요청을 보내고 요청 헤더에Authorization: Bearer <your_token>
을 추가합니다.
curl -X GET http://localhost:8000/protected -H "Authorization: Bearer <your_token>"
결론
위의 단계를 통해 FastAPI에서 JWT를 사용하여 인증하는 방법을 배웠습니다. JWT는 사용자 ID를 관리하는 안전하고 편리한 방법을 제공하여 분산 시스템 간의 인증을 더욱 효율적으로 만듭니다. 실제 응용 프로그램에서는 만료 시간 추가, 클레임 사용자 정의 등 필요에 따라 JWT의 생성 및 검증 로직을 조정할 수 있습니다.
Leapcell: 최고의 서버리스 웹 호스팅
마지막으로, Python 서비스를 배포하는 데 가장 적합한 플랫폼인 **Leapcell**을 추천합니다.
🚀 좋아하는 언어로 빌드
JavaScript, Python, Go 또는 Rust로 손쉽게 개발하세요.
🌍 무료로 무제한 프로젝트 배포
사용한 만큼만 지불하세요. 요청도 없고, 요금도 없습니다.
⚡ 사용량에 따라 지불, 숨겨진 비용 없음
유휴 요금 없이 원활한 확장성만 제공합니다.
🔹 Twitter에서 팔로우하세요: @LeapcellHQ