Die Beherrschung der FastAPI-Sicherheit: Ein umfassender Leitfaden zu OAuth2 mit Passwort-Hashing und JWT-Bearer-Tokens

Im Zeitalter der digitalen Transformation ist die Sicherung von Webanwendungen von größter Bedeutung geworden. FastAPI ist eines der beliebtesten Frameworks zum Erstellen von APIs mit Python und bietet mehrere Optionen zum Absichern von Endpunkten und Verwalten der Authentifizierung. Dieser umfassende Leitfaden führt Sie durch die Implementierung von OAuth2 mit Passwort-Hashing und JWT-Bearer-Tokens in FastAPI.

Einführung in OAuth2

OAuth2 ist ein weit verbreitetes Autorisierungs-Framework, das Anwendungen ermöglicht, eingeschränkten Zugriff auf Benutzerkonten auf einem HTTP-Dienst zu erhalten. Es funktioniert durch die Delegierung der Benutzerauthentifizierung an einen Drittanbieter, was eine sicherere und effizientere Zugriffskontrolle ermöglicht.

Schlüsselbegriffe von OAuth2

  • Ressourceneigentümer: Der Benutzer, der einer Anwendung den Zugriff auf sein Konto autorisiert.
  • Client: Die Anwendung, die den Zugriff auf das Benutzerkonto anfordert.
  • Autorisierungsserver: Der Server, der Token ausstellt, nachdem der Ressourceneigentümer erfolgreich authentifiziert und die Autorisierung erhalten wurde.
  • Ressourcenserver: Der Server, der die Daten des Benutzers speichert und Zugriffstoken für den Ressourcenzugriff akzeptiert.

Einrichten von FastAPI für OAuth2

Wir beginnen mit der Einrichtung einer grundlegenden FastAPI-Anwendung und fügen die notwendigen Bibliotheken zur Implementierung von OAuth2 hinzu.

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
from jose import JWTError, jwt
from pydantic import BaseModel
from datetime import datetime, timedelta
from typing import Optional

Die hier genannten Bibliotheken und Module sind essentiell für die Handhabung von Abhängigkeiten, HTTP-Ausnahmen, Passwort-Hashing und JSON-Web-Tokens (JWT).

Implementierung des Passwort-Hashings

Das Speichern von Klartext-Passwörtern ist niemals eine gute Praxis. Stattdessen hashen wir Passwörter mit passlib, einer Passwort-Hashing-Bibliothek für Python.

Erstellen einer Passwort-Hashing-Funktion

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
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)

Hier überprüft verify_password, ob das Klartext-Passwort mit dem gehashten Passwort übereinstimmt, während get_password_hash ein Klartext-Passwort hasht.

Erstellen von Modellen und Token-Dienstprogrammen

Wir benötigen Benutzer-Modelle und Dienstprogramme zum Generieren und Dekodieren von JWT-Tokens.

Benutzer- und Token-Modelle

class User(BaseModel):
    username: str
class UserInDB(User):
    hashed_password: str
class Token(BaseModel):
    access_token: str
    token_type: str
class TokenData(BaseModel):
    username: Optional[str] = None

User repräsentiert einen Benutzer, UserInDB enthält das gehashte Passwort, und Token und TokenData behandeln JWT-Tokens.

JWT-Dienstprogramme

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

Die Funktion create_access_token generiert JWT-Tokens mit einer Ablaufzeit.

Handhabung von Authentifizierung und Autorisierung

Wir verwenden die OAuth2PasswordBearer- und OAuth2PasswordRequestForm-Klassen zur Handhabung der Authentifizierung.

Abhängigkeitsinjektion für sichere Endpunkte

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
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
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user

Dieser Code überprüft das JWT-Token und ruft den aktuellen Benutzer aus den Token-Daten ab.

Erstellen von Routen zur Token-Generierung und sicherem Zugriff

app = FastAPI()
@app.post("/token", response_model=Token)
async def login_for_access_token(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="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"}
@app.get("/users/me", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

Der Endpunkt /token generiert ein JWT-Token, und /users/me gibt die Daten des aktuell authentifizierten Benutzers zurück.

Schlussfolgerung

Die Implementierung von OAuth2 mit Passwort-Hashing und JWT-Bearer-Tokens in FastAPI bietet eine robuste Sicherheit für Ihre APIs. Dieser Leitfaden behandelte die wesentlichen Komponenten, einschließlich der Einrichtung von FastAPI, der Implementierung von Passwort-Hashing, der Erstellung von JWT-Tokens und der Sicherung von Endpunkten. Durch die Befolgung dieser Schritte können Sie die Sicherheit Ihrer Anwendungen verbessern und gleichzeitig die Effizienz von FastAPI nutzen.

Bereit, Ihre FastAPI-Anwendung auf die nächste Stufe zu heben? Beginnen Sie noch heute mit der Implementierung dieser Sicherheitspraktiken, um Ihre Benutzer und Daten zu schützen.