| 모듈 | 주요 기능 | 언제 사용하나요? |
|---|---|---|
python-jose[cryptography] | JWT 생성, 검증, 암호화 등 보안 토큰 작업 | 인증 시스템 (로그인 등) |
passlib[bcrypt] | 비밀번호 해싱 및 검증 | 회원가입/로그인 비밀번호 처리 |
python-multipart | multipart/form-data 요청 처리 | 파일 업로드 API 등 |
router = APIRouter(
prefix='/auth',
tags=['auth']
)
# main.py
import auth
app = FastAPI()
app.include_router(auth.router) # auth.py에서 만든 라우터를 메인 애플리케이션에 틍록하는 작업brypt_context = CryptContext(schemes=['bcrypt'],deprecated='auto')
비밀번호 해싱
hashed_password = bcrypt_context.hash("plain_password")
# 비밀번호 검증
is_valid = bcrypt_context.verify("plain_password", hashed_password) deprecated='auto' : 어떤 해시 알고리즘을 더 이상 기본으로 사용하지 않을 것인지 자동으로 판단하게 함 향후 알고리즘 교체/ 마이그레이션 전략에 유용 bcrypt: 비밀번호 저장용 안전한 해시 알고리즘 SHA256는 빠르기 떄문에 공격자도 빠르게 시도를 할 수 있다. Salt가 없어서 같은 비밀번호는 같은 해시값이다. 🔐 왜 bcrypt가 필요한가? ✅ 일반적인 해시 함수(e.g. SHA256)는:매우 빠르다 → 공격자도 빠르게 시도할 수 있음
salt가 없으면 같은 비밀번호는 같은 해시값 → rainbow table 공격에 취약
✅ bcrypt는 다음과 같은 보안 기능을 제공:
| 기능 | 설명 |
|---|---|
| Salt 내장 | 무작위 salt 자동 추가 → 해시 중복 방지 |
| 느린 계산 속도 | 고의로 느리게 처리 → 공격자가 빠르게 추측 시도 못 함 |
| Cost 설정 가능 | rounds나 cost 값을 조정하여 연산량 조절 가능 |
OAuth2 방식의 토큰 인증을 구현할 떄 사용하는 의존성 설정 객체
🔍 상세 설명:
OAuth2PasswordBearer는 FastAPI가 제공하는 인증 방식 중 하나로,
tokenUrl='/auth/token'는 토큰을 발급받기 위한 엔드포인트 URL을 의미합니다.
- 예: 클라이언트는 /auth/token에 사용자명/비번을 POST해서 토큰을 받고,
- 이후 요청 시 Authorization: Bearer 형태로 헤더를 보냅니다.
from fastapi import Depends
# 보호된 엔드포인트 예시
@app.get("/protected")
async def protected_route(token: str = Depends(oauth2_bearer)):
return {"token": token}
✅결론 :
OAuth2PasswordBearer는 단순히 헤더에서 토큰 문자열만 추출해줄 뿐!
자동 데이터 검증(Validation)
BaseModel을 상속한 클래스는 타입 힌트를 기반으로 입력값을 검증
from pydantic import BaseModel
class CreateUserRequest(BaseModel):
username: str
password: str
data = CreateUserRequest(username="john", password="1234") # OK
data = CreateUserRequest(username=123, password=True) # 에러 발생
→ username에 정수가 들어오거나 password에 불리언이 들어오면 ValidationError가 발생!!
자동 타입 변환(Type Coercion)
가능하다면, pydantic은 값을 지정된 타입으로 변환할려고 시도함.
user = CreateUserRequest(username=123, password=456)
print(user.username) # '123'
print(user.password) # '456'
직렬화 지원(Serialization)
.dict() 또는 .json() 메서드로 Python 객체를 딕셔너리나 JSON으로 변환 가능
user.dict()
# {'username': 'john', 'password': '1234'}
user.json()
# '{"username": "john", "password": "1234"}'
IDE지원 및 자동완성
BaseModel 을 사용하면 타입 힌트 기반 자동완성과 오타 방지에 매우 유리하다.
보안, 문서화 및 FastAPI연계
Pydantic은 FastAPI와 같이 사용할 때, 요청/응답 바디 검증, 자동 Swagger 문서화 등에 아주 유용하게 사용됩니다.
class Token(BaseModel):
access_token: str
token_type: str
정의 클래스 사용 법!
@app.post("/login", response_model=Token)
def login(user: CreateUserRequest):
...
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
db_dependency = Annotated[Session, Depends(get_db)]
@router.post("/", status_code=status.HTTP_201_CREATED)
# db_dependency : 의존성 주읩으로 SQLALchemy의 Session 객체를 받아온다.
async def create_user(db: db_dependency, create_user_request: CreateUserRequest):
create_user_model = Users(
username= create_user_request.username,
hashed_password = bcrypt_context.hash(create_user_request.password)
)
db.add(create_user_model)
db.commit() Annotated[기본타입, 메타데이터] : 타입 힌트 확장 도구! db_dependency = Annotated[Session, Depends(get_db)] SQLAlchemy 세션을 자동으로 주입받기 위해 사용하는 의존성 정의 → "db_dependency는 Session 타입이고, get_db() 함수를 실행해서 얻은 결과를 여기에 넣어줘." 🔹 create_user_request 👉 클라이언트가 보내는 요청 데이터입니다. 보통 JSON body로 전송되고, FastAPI는 이를 Pydantic 모델로 자동 파싱합니다.{
"username": "johndoe",
"email": "john@example.com",
"password": "secret123"
} 이런 JSON이 오면, FastAPI는 create_user_request: CreateUserRequest로 자동 변환 🔹 db 👉 FastAPI가 자동으로 만들어서 넣어주는 의존성입니다. Depends(get_db)를 통해 get_db() 함수가 호출되고, 그 결과인 SQLAlchemy 세션(Session) 객체가 db 매개변수로 들어갑니다. 즉, 클라이언트는 db를 몰라도 되고, FastAPI가 내부적으로 관리해줍니다.