파이썬/Fast API
FastAPI Security: API 보안 구현
코샵
2025. 2. 24. 11:41
반응형
# 기본 설치 (FastAPI에 포함되어 있음)
pip install fastapi[all]
pip install python-jose[cryptography] # JWT 토큰용
pip install passlib[bcrypt] # 비밀번호 해싱용
OAuth2 비밀번호 인증
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
# 기본 설정
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
app = FastAPI()
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password"
)
access_token = create_access_token(data={"sub": user.username})
return {"access_token": access_token, "token_type": "bearer"}
API Key 인증
from fastapi.security import APIKeyHeader, APIKeyQuery
# 헤더 기반 API 키
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=True)
# 쿼리 파라미터 기반 API 키
api_key_query = APIKeyQuery(name="api_key", auto_error=True)
@app.get("/secure/header")
async def secure_endpoint(api_key: str = Depends(api_key_header)):
if not is_valid_api_key(api_key):
raise HTTPException(status_code=403, detail="Invalid API Key")
return {"message": "Secured by header"}
HTTP Basic 인증
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
security = HTTPBasic()
@app.get("/users/me")
async def get_current_user(credentials: HTTPBasicCredentials = Depends(security)):
correct_username = secrets.compare_digest(
credentials.username, "admin"
)
correct_password = secrets.compare_digest(
credentials.password, "secret"
)
if not (correct_username and correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
return {"username": credentials.username}
JWT 토큰 구현
from datetime import datetime, timedelta
from typing import Optional
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
expire = datetime.utcnow() + (
expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def get_current_user(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 username
복합 보안 구현
from fastapi.security import OAuth2PasswordBearer, APIKeyHeader
from typing import Union
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
async def get_authorization(
token: Union[str, None] = Depends(oauth2_scheme),
api_key: Union[str, None] = Depends(api_key_header)
):
if token:
return await get_current_user(token)
elif api_key:
return verify_api_key(api_key)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
)
@app.get("/secure")
async def secure_endpoint(auth = Depends(get_authorization)):
return {"auth": auth}
CORS 설정
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
보안 미들웨어
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
# HTTPS 리다이렉션
app.add_middleware(HTTPSRedirectMiddleware)
# 신뢰할 수 있는 호스트
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["example.com", "*.example.com"]
)
주요 기능 및 장점
- 다양한 인증 방식
- OAuth2 지원
- API 키 인증
- Basic 인증
- JWT 토큰
- 유연한 구성
- 여러 인증 방식 조합
- 커스텀 인증 로직
- 세분화된 접근 제어
- 보안 기능
- CORS 관리
- HTTPS 강제
- 호스트 검증
- 사용자 경험
- 명확한 에러 메시지
- 표준 인증 흐름
- 문서화 지원
FastAPI.security를 사용하면 안전하고 표준을 준수하는 API 보안을 구현할 수 있습니다.