Wie man die Autorisierung und Authentifizierung in FastAPI schnell einrichtet und erklärt
Hier ist eine Schritt-für-Schritt-Anleitung zur Einrichtung von Autorisierung und Authentifizierung in FastAPI unter Verwendung von OAuth2 und JWT:

Beginnen wir mit der Organisation des Codes in separate Dateien.
Erstellen Sie zunächst eine neue Datei namens models.py für Ihre Pydantic-Modelle:

models.py:
```
from pydantic import BaseModel

class User(BaseModel):
    username: str
    email: str
    hashed_password: str

class Token(BaseModel):
    access_token: str
    token_type: str
```

Als Nächstes erstellen Sie eine weitere neue Datei namens dependencies.py für Ihre Abhängigkeitsfunktionen:

dependencies.py:
```
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt, JWTError
from typing import Optional
import os
import secrets

from models import User
from utils import get_user, verify_password

SECRET_KEY = os.getenv("SECRET_KEY", default=secrets.token_hex(32))
ALGORITHM = "HS256"

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="Konnte Anmeldeinformationen nicht validieren",
        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 = {"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
```

Erstellen Sie nun eine neue Datei namens utils.py für Ihre Hilfsfunktionen:

utils.py:
```
from passlib.context import CryptContext
from jose import jwt
from datetime import datetime, timedelta
from models import User

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:
        user_dict = db[username]
        return User(**user_dict)

def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user

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=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt
```

Nun importieren Sie in Ihrer main.py diese Module und entfernen den doppelten Code:

main.py:
```
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from datetime import timedelta
from passlib.context import CryptContext
import secrets

from models import User, Token
from dependencies import oauth2_scheme, get_current_user
from utils import authenticate_user, create_access_token, get_user

app = FastAPI()

ACCESS_TOKEN_EXPIRE_MINUTES = 30

# Fake-Benutzer-DB
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "email": "johndoe@example.com",
        "hashed_password": CryptContext(schemes=["bcrypt"], deprecated="auto").hash("password123"),
    }
}

@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="Falscher Benutzername oder falsches Passwort",
            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
```

Jetzt haben Sie eine FastAPI-Anwendung mit Authentifizierung und Autorisierung unter Verwendung von OAuth2 und JWT. Sie können den Endpunkt /token testen, um einen Zugriffstoken zu erhalten, und ihn dann verwenden, um auf den gesicherten Endpunkt /users/me zuzugreifen.

In Zukunft möchten Sie die fake_users_db durch eine tatsächliche Datenbank ersetzen. Sie können eine ORM wie SQLAlchemy oder eine andere Datenbankbibliothek verwenden, um Ihre Datenbankoperationen zu verwalten.

Bitte lassen Sie mich wissen, wenn Sie daran interessiert sind, die Mock-Datenbank fake_users_db durch eine echte Datenbankimplementierung zu ersetzen oder andere Änderungen vorzunehmen.