FastAPI 서버개발, 보안, FastAPI의 인증 방식

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 뛰어난 성능과 직관적인 문법으로 인기를 끌고 있습니다. 이 글에서는 FastAPI를 사용하여 서버를 개발하는 방법, 보안의 중요성, 그리고 다양한 인증 방법에 대해 자세히 설명하겠습니다.

1. FastAPI 개요

FastAPI는 RESTful API를 빠르게 구축하기 위한 프레임워크입니다. Python의 타입 힌트를 활용하여 코드의 가독성과 유효성을 높이면서, 자동으로 API 문서를 생성하는 기능을 제공합니다. FastAPI는 Starlette와 Pydantic을 기반으로 하여 높은 성능과 데이터 검증 기능을 함께 제공합니다.

2. FastAPI의 설치와 기본 설정

FastAPI와 함께 Uvicorn ASGI 서버를 설치해야 합니다. 다음과 같은 명령어를 사용하여 설치할 수 있습니다:

pip install fastapi uvicorn

2.1 Hello World 예제

FastAPI의 기본적인 구조를 이해하기 위해 간단한 Hello World API를 만들어보겠습니다.


from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"Hello": "World"}
    

위의 코드를 main.py 파일로 저장한 뒤, 다음 명령어로 서버를 실행할 수 있습니다:

uvicorn main:app --reload

이제 브라우저에서 http://127.0.0.1:8000를 열면 “Hello, World” JSON 응답을 확인할 수 있습니다.

3. 서버 보안의 중요성

소프트웨어 개발에서 보안은 매우 중요한 요소입니다. 특히, API를 통해 데이터와 기능에 접근하게 될 경우, 보안이 취약하다면 해킹의 위험성이 높아집니다. FastAPI를 사용할 때는 다음과 같은 보안 요소를 고려해야 합니다:

  • 데이터 암호화
  • 사용자 인증 및 권한 부여
  • 입력 데이터 검증
  • 로그 기록 및 모니터링

4. FastAPI의 인증 방식

FastAPI는 다양한 인증 방식을 지원합니다. 그 중에서 가장 일반적인 방식은 JWT 토큰 인증과 OAuth2입니다. 이번 섹션에서는 JWT 인증 방식을 중심으로 설명하겠습니다.

4.1 JWT( JSON Web Token) 인증

JWT는 두 개의 엔드포인트(로그인과 인증된 사용자 확인)를 통해 사용됩니다. 사용자 정보를 안전하게 저장하고 전달하는 방법 중 하나입니다. JWT 웹 토큰은 주로 사용자 인증 및 정보 교환에 사용되며, 다음과 같은 구조를 가집니다:

  • Header: 토큰의 유형과 서명 알고리즘을 정의합니다.
  • Payload: 사용자 정보나 기타 데이터를 포함합니다.
  • Signature: Header와 Payload를 인코딩하여 비밀 키로 서명한 값입니다.

4.2 FastAPI로 JWT 인증 구현하기

FastAPI에서 JWT 인증을 구현하는 방법은 다음과 같습니다:

4.2.1 필요한 라이브러리 설치

JWT를 사용하기 위해서는 PyJWT와 passlib를 설치해야 합니다. 아래 명령어로 설치할 수 있습니다:

pip install pyjwt passlib[bcrypt]

4.2.2 JWT 유틸리티 함수

토큰 생성 및 검증을 위한 헬퍼 함수를 작성합니다.


import jwt
from datetime import datetime, timedelta
from typing import Dict

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt
    

4.2.3 FastAPI 사용자 모델

사용자 모델을 작성하고, 인증을 위한 엔드포인트를 추가합니다.


from fastapi import FastAPI, Depends, HTTPException
from passlib.context import CryptContext

app = FastAPI()

class User:
    def __init__(self, username: str, password: str):
        self.username = username
        self.password = password

fake_users_db = {
    "johndoe": User(username="johndoe", password="$2b$12$KIXT8j/Nu1H3VzOZL5rO.ulpYb/JgVdY2VZ5ZFkElXju2GZBeY1Fe")
}

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_user(db, username: str):
    if username in db:
        return db[username]
    return None

@app.post("/token")
async def login(username: str, password: str):
    user = get_user(fake_users_db, username)
    if not user or not verify_password(password, user.password):
        raise HTTPException(
            status_code=401,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={"sub": user.username}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}
    

4.2.4 보호된 엔드포인트 생성

인증된 사용자만 접근할 수 있는 보호된 엔드포인트를 추가합니다.


from fastapi import Security
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=401,
        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 jwt.PyJWTError:
        raise credentials_exception
    return {"username": username}
    

5. 결론

FastAPI는 높은 성능과 가독성을 제공하는 훌륭한 웹 프레임워크입니다. 보안은 애플리케이션 개발에 있어 중요한 요소로, JWT 인증은 사용자 인증을 안전하게 수행할 수 있는 방법 중 하나입니다. 이번 글에서 рассмотрены(JWT) 인증 구현 방법을 통해 FastAPI의 발전 가능성과 효율성을 알 수 있는 기회가 되었기를 바랍니다.

FastAPI와 관련하여 더 많은 자료를 참고하시려면 FastAPI 공식 문서를 참조하시기 바랍니다.