FastAPI에서 세션 관리와 로그인, 로그아웃 기능은 주로 쿠키와 JWT(JSON Web Tokens) 또는 OAuth2를 사용하여 구현할 수 있습니다. 세션 관리는 서버에 상태를 저장하는 전통적인 방식과, 상태를 저장하지 않고 토큰을 사용하는 방법으로 나뉩니다. 여기서는 JWT 기반의 로그인/로그아웃과 세션 기반의 로그인/로그아웃 방법을 설명하겠습니다.
1. FastAPI에서 JWT 기반 로그인/로그아웃 구현
JWT는 서버에 세션 정보를 저장하지 않고도 인증할 수 있는 방식을 제공하며, 각 요청마다 JWT를 사용하여 인증합니다. 이를 통해 애플리케이션은 무상태(stateless)로 유지될 수 있습니다.
JWT 설정 및 구현
필요한 라이브러리 설치
FastAPI와 JWT를 사용하기 위해 필요한 라이브러리를 설치합니다.
pip install fastapi[all] pyjwt passlib
JWT 토큰 생성 및 검증을 위한 설정
FastAPI에서 JWT를 생성하고 검증하는 예제를 살펴보겠습니다.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from datetime import datetime, timedelta
from typing import Optional
import jwt
from passlib.context import CryptContext
# 앱 생성
app = FastAPI()
# 보안 설정
SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# 유저 데이터 예시
fake_users_db = {
"testuser": {
"username": "testuser",
"full_name": "Test User",
"email": "test@example.com",
"hashed_password": "$2b$12$KIXdFh6fDF/hjEPGzTj6me2VVd./tFMyOP58/GKse4Gzi8TOSwlxu", # "password"의 해시값
}
}
# 비밀번호 해싱 도구 설정
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2를 사용한 비밀번호 기반 인증
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# 유저 모델 정의
class User(BaseModel):
username: str
email: Optional[str] = None
full_name: Optional[str] = None
class UserInDB(User):
hashed_password: str
class Token(BaseModel):
access_token: str
token_type: str
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
return pwd_context.hash(password)
def get_user(db, username: str):
if username in db:
user_dict = db[username]
return UserInDB(**user_dict)
def authenticate_user(fake_db, username: str, password: str):
user = get_user(fake_db, username)
if not user or not verify_password(password, user.hashed_password):
return False
return user
def create_access_token(data: dict, expires_delta: Optional[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)
@app.post("/token", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(data={"sub": user.username}, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
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)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials")
token_data = {"username": username}
except jwt.PyJWTError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials")
user = get_user(fake_users_db, username=token_data["username"])
if user is None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found")
return user
코드 설명
login
엔드포인트는 사용자의 자격 증명을 검증하고 JWT를 발급합니다.read_users_me
엔드포인트는 발급된 JWT를 통해 사용자를 인증합니다. JWT가 유효하지 않으면401 Unauthorized
응답을 반환합니다.- JWT 토큰은
sub
필드에 사용자의 이름을 포함하고, 만료 시간을 설정할 수 있습니다.
실행 및 테스트
서버 실행 후 /token
엔드포인트에 POST 요청을 보내어 access_token
을 받습니다. 이 토큰을 /users/me
엔드포인트의 Authorization
헤더에 Bearer
타입으로 포함하여 요청하면 사용자 정보를 확인할 수 있습니다.
2. FastAPI에서 쿠키 기반 세션 관리 및 로그인/로그아웃 구현
세션 기반 인증은 보통 쿠키를 사용하여 세션 정보를 관리하며, 사용자 정보를 서버에 저장하여 관리합니다. 다음은 간단한 세션 기반 로그인/로그아웃 예제입니다.
FastAPI에서 세션 관리 예제
세션 관리를 위해 starlette.middleware.sessions를 사용하여 세션 미들웨어를 추가합니다.
필요한 라이브러리 설치
pip install fastapi[all]
세션을 이용한 로그인 구현
from fastapi import FastAPI, Request, Depends, Form, HTTPException
from fastapi.responses import RedirectResponse
from fastapi.middleware.sessions import SessionMiddleware
from starlette.responses import JSONResponse
# FastAPI 앱 생성 및 세션 미들웨어 추가
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="mysecretkey")
# 유저 데이터베이스 예시
fake_users_db = {
"testuser": {
"username": "testuser",
"password": "password"
}
}
def authenticate_user(username: str, password: str):
user = fake_users_db.get(username)
return user and user["password"] == password
@app.post("/login")
async def login(request: Request, username: str = Form(...), password: str = Form(...)):
if authenticate_user(username, password):
request.session["username"] = username
return JSONResponse(content={"message": "Login successful"})
else:
raise HTTPException(status_code=400, detail="Invalid credentials")
@app.get("/logout")
async def logout(request: Request):
request.session.clear()
return JSONResponse(content={"message": "Logout successful"})
@app.get("/profile")
async def profile(request: Request):
username = request.session.get("username")
if not username:
raise HTTPException(status_code=401, detail="Not authenticated")
return {"username": username}
코드 설명
SessionMiddleware
: 쿠키 기반 세션을 위해SessionMiddleware
를 FastAPI 애플리케이션에 추가합니다.login
엔드포인트: 로그인 자격을 확인하고, 세션에 사용자 정보를 저장합니다.logout
엔드포인트: 세션을 삭제하여 사용자를 로그아웃합니다.profile
엔드포인트: 세션에 저장된 사용자 정보를 확인합니다. 인증되지 않은 사용자는401 Unauthorized
응답을 받습니다.
실행 및 테스트
로그인 후 /profile
엔드포인트를 호출하면 세션에 저장된 사용자 정보를 확인할 수 있습니다. 로그아웃 요청 후 /profile
을 다시 호출하면 인증되지 않은 상태로 간주됩니다.
결론
FastAPI에서 JWT와 세션 기반 로그인/로그아웃을 설정하는 방법을 살펴보았습니다. FastAPI는 다양한 인증 방식을 지원하며, RESTful API 및 인증 시스템을 효율적으로 구현할 수 있습니다.
'마이크로 웹 프레임워크' 카테고리의 다른 글
[마이크로 웹 프레임워크] 플라스크 소개 및 예제 2 (2) | 2024.10.22 |
---|---|
[마이크로 웹 프레임워크] 파이썬 Sanic 프레임워크란? (0) | 2024.10.20 |
[마이크로 웹 프레임워크] Falcon 고성능 웹 프레임워크 1 (4) | 2024.10.19 |
[마이크로 웹 프레임워크] FastAPI 마이크로 웹 프레임워크 1 (2) | 2024.10.18 |
[마이크로 웹 프레임워크] 파이썬 Bottle 웹 프레임워크 1 (2) | 2024.10.17 |