]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
🌐 Add German translation for `docs/de/docs/tutorial/security/simple-oauth2.md` (...
authorNils Lindemann <nilslindemann@tutanota.com>
Sat, 30 Mar 2024 18:08:44 +0000 (19:08 +0100)
committerGitHub <noreply@github.com>
Sat, 30 Mar 2024 18:08:44 +0000 (13:08 -0500)
docs/de/docs/tutorial/security/simple-oauth2.md [new file with mode: 0644]

diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md
new file mode 100644 (file)
index 0000000..ed280d4
--- /dev/null
@@ -0,0 +1,435 @@
+# Einfaches OAuth2 mit Password und Bearer
+
+Lassen Sie uns nun auf dem vorherigen Kapitel aufbauen und die fehlenden Teile hinzufĂŒgen, um einen vollstĂ€ndigen Sicherheits-Flow zu erhalten.
+
+## `username` und `password` entgegennehmen
+
+Wir werden **FastAPIs** Sicherheits-Werkzeuge verwenden, um den `username` und das `password` entgegenzunehmen.
+
+OAuth2 spezifiziert, dass der Client/Benutzer bei Verwendung des â€žPassword Flow“ (den wir verwenden) die Felder `username` und `password` als Formulardaten senden muss.
+
+Und die Spezifikation sagt, dass die Felder so benannt werden mĂŒssen. `user-name` oder `email` wĂŒrde also nicht funktionieren.
+
+Aber keine Sorge, Sie können sie Ihren Endbenutzern im Frontend so anzeigen, wie Sie möchten.
+
+Und Ihre Datenbankmodelle können beliebige andere Namen verwenden.
+
+Aber fĂŒr die Login-*Pfadoperation* mĂŒssen wir diese Namen verwenden, um mit der Spezifikation kompatibel zu sein (und beispielsweise das integrierte API-Dokumentationssystem verwenden zu können).
+
+Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten gesendet werden mĂŒssen (hier also kein JSON).
+
+### <abbr title="Geltungsbereich">`scope`</abbr>
+
+Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" („Geltungsbereich“) senden kann.
+
+Der Name des Formularfelds lautet `scope` (im Singular), tatsĂ€chlich handelt es sich jedoch um einen langen String mit durch Leerzeichen getrennten â€žScopes“.
+
+Jeder â€žScope“ ist nur ein String (ohne Leerzeichen).
+
+Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu deklarieren, zum Beispiel:
+
+* `users:read` oder `users:write` sind gĂ€ngige Beispiele.
+* `instagram_basic` wird von Facebook / Instagram verwendet.
+* `https://www.googleapis.com/auth/drive` wird von Google verwendet.
+
+!!! info
+    In OAuth2 ist ein â€žScope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
+
+    Es spielt keine Rolle, ob er andere Zeichen wie `:` enthĂ€lt oder ob es eine URL ist.
+
+    Diese Details sind implementierungsspezifisch.
+
+    FĂŒr OAuth2 sind es einfach nur Strings.
+
+## Code, um `username` und `password` entgegenzunehmen.
+
+Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um das zu erledigen.
+
+### `OAuth2PasswordRequestForm`
+
+Importieren Sie zunĂ€chst `OAuth2PasswordRequestForm` und verwenden Sie es als AbhĂ€ngigkeit mit `Depends` in der *Pfadoperation* fĂŒr `/token`:
+
+=== "Python 3.10+"
+
+    ```Python hl_lines="4  78"
+    {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+    ```
+
+=== "Python 3.9+"
+
+    ```Python hl_lines="4  78"
+    {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+    ```
+
+=== "Python 3.8+"
+
+    ```Python hl_lines="4  79"
+    {!> ../../../docs_src/security/tutorial003_an.py!}
+    ```
+
+=== "Python 3.10+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="2  74"
+    {!> ../../../docs_src/security/tutorial003_py310.py!}
+    ```
+
+=== "Python 3.8+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="4  76"
+    {!> ../../../docs_src/security/tutorial003.py!}
+    ```
+
+`OAuth2PasswordRequestForm` ist eine KlassenabhĂ€ngigkeit, die einen Formularbody deklariert mit:
+
+* Dem `username`.
+* Dem `password`.
+* Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings.
+* Einem optionalen `grant_type` („Art der Anmeldung“).
+
+!!! tip "Tipp"
+    Die OAuth2-Spezifikation *erfordert* tatsĂ€chlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht.
+
+    Wenn Sie es erzwingen mĂŒssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`.
+
+* Eine optionale `client_id` (benötigen wir fĂŒr unser Beispiel nicht).
+* Ein optionales `client_secret` (benötigen wir fĂŒr unser Beispiel nicht).
+
+!!! info
+    `OAuth2PasswordRequestForm` ist keine spezielle Klasse fĂŒr **FastAPI**, so wie `OAuth2PasswordBearer`.
+
+    `OAuth2PasswordBearer` lĂ€sst **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefĂŒgt.
+
+    Aber `OAuth2PasswordRequestForm` ist nur eine KlassenabhĂ€ngigkeit, die Sie selbst hĂ€tten schreiben können, oder Sie hĂ€tten `Form`ular-Parameter direkt deklarieren können.
+
+    Da es sich jedoch um einen hĂ€ufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt.
+
+### Die Formulardaten verwenden
+
+!!! tip "Tipp"
+    Die Instanz der KlassenabhĂ€ngigkeit `OAuth2PasswordRequestForm` verfĂŒgt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, ĂŒber das Attribut `scopes` mit einer tatsĂ€chlichen Liste von Strings, einem fĂŒr jeden gesendeten Scope.
+
+    In diesem Beispiel verwenden wir keine `scopes`, aber die FunktionalitĂ€t ist vorhanden, wenn Sie sie benötigen.
+
+Rufen Sie nun die Benutzerdaten aus der (gefakten) Datenbank ab, fĂŒr diesen `username` aus dem Formularfeld.
+
+Wenn es keinen solchen Benutzer gibt, geben wir die Fehlermeldung â€žIncorrect username or password“ zurĂŒck.
+
+FĂŒr den Fehler verwenden wir die Exception `HTTPException`:
+
+=== "Python 3.10+"
+
+    ```Python hl_lines="3  79-81"
+    {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+    ```
+
+=== "Python 3.9+"
+
+    ```Python hl_lines="3  79-81"
+    {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+    ```
+
+=== "Python 3.8+"
+
+    ```Python hl_lines="3  80-82"
+    {!> ../../../docs_src/security/tutorial003_an.py!}
+    ```
+
+=== "Python 3.10+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="1  75-77"
+    {!> ../../../docs_src/security/tutorial003_py310.py!}
+    ```
+
+=== "Python 3.8+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="3  77-79"
+    {!> ../../../docs_src/security/tutorial003.py!}
+    ```
+
+### Das Passwort ĂŒberprĂŒfen
+
+Zu diesem Zeitpunkt liegen uns die Benutzerdaten aus unserer Datenbank vor, das Passwort haben wir jedoch noch nicht ĂŒberprĂŒft.
+
+Lassen Sie uns diese Daten zunĂ€chst in das Pydantic-Modell `UserInDB` einfĂŒgen.
+
+Sie sollten niemals Klartext-Passwörter speichern, daher verwenden wir ein (gefaktes) Passwort-Hashing-System.
+
+Wenn die Passwörter nicht ĂŒbereinstimmen, geben wir denselben Fehler zurĂŒck.
+
+#### Passwort-Hashing
+
+„Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht.
+
+Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) ĂŒbergeben, erhalten Sie genau den gleichen Kauderwelsch.
+
+Sie können jedoch nicht vom Kauderwelsch zurĂŒck zum Passwort konvertieren.
+
+##### Warum Passwort-Hashing verwenden?
+
+Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes.
+
+Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer ĂŒberall das gleiche Passwort verwenden, wĂ€re dies gefĂ€hrlich).
+
+=== "Python 3.10+"
+
+    ```Python hl_lines="82-85"
+    {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+    ```
+
+=== "Python 3.9+"
+
+    ```Python hl_lines="82-85"
+    {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+    ```
+
+=== "Python 3.8+"
+
+    ```Python hl_lines="83-86"
+    {!> ../../../docs_src/security/tutorial003_an.py!}
+    ```
+
+=== "Python 3.10+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="78-81"
+    {!> ../../../docs_src/security/tutorial003_py310.py!}
+    ```
+
+=== "Python 3.8+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="80-83"
+    {!> ../../../docs_src/security/tutorial003.py!}
+    ```
+
+#### Ăœber `**user_dict`
+
+`UserInDB(**user_dict)` bedeutet:
+
+*Übergib die SchlĂŒssel und Werte des `user_dict` direkt als SchlĂŒssel-Wert-Argumente, Ă€quivalent zu:*
+
+```Python
+UserInDB(
+    username = user_dict["username"],
+    email = user_dict["email"],
+    full_name = user_dict["full_name"],
+    disabled = user_dict["disabled"],
+    hashed_password = user_dict["hashed_password"],
+)
+```
+
+!!! info
+    Eine ausfĂŒhrlichere ErklĂ€rung von `**user_dict` finden Sie in [der Dokumentation fĂŒr **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}.
+
+## Den Token zurĂŒckgeben
+
+Die Response des `token`-Endpunkts muss ein JSON-Objekt sein.
+
+Es sollte einen `token_type` haben. Da wir in unserem Fall â€žBearer“-Token verwenden, sollte der Token-Typ "`bearer`" sein.
+
+Und es sollte einen `access_token` haben, mit einem String, der unseren Zugriffstoken enthĂ€lt.
+
+In diesem einfachen Beispiel gehen wir einfach völlig unsicher vor und geben denselben `username` wie der Token zurĂŒck.
+
+!!! tip "Tipp"
+    Im nĂ€chsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und <abbr title="JSON Web Tokens">JWT</abbr>-Tokens.
+
+    Aber konzentrieren wir uns zunĂ€chst auf die spezifischen Details, die wir benötigen.
+
+=== "Python 3.10+"
+
+    ```Python hl_lines="87"
+    {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+    ```
+
+=== "Python 3.9+"
+
+    ```Python hl_lines="87"
+    {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+    ```
+
+=== "Python 3.8+"
+
+    ```Python hl_lines="88"
+    {!> ../../../docs_src/security/tutorial003_an.py!}
+    ```
+
+=== "Python 3.10+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="83"
+    {!> ../../../docs_src/security/tutorial003_py310.py!}
+    ```
+
+=== "Python 3.8+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="85"
+    {!> ../../../docs_src/security/tutorial003.py!}
+    ```
+
+!!! tip "Tipp"
+    GemĂ€ĂŸ der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurĂŒckgeben, genau wie in diesem Beispiel.
+
+    Das mĂŒssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-SchlĂŒssel verwenden.
+
+    Es ist fast das Einzige, woran Sie denken mĂŒssen, es selbst richtigzumachen und die Spezifikationen einzuhalten.
+
+    Den Rest erledigt **FastAPI** fĂŒr Sie.
+
+## Die AbhĂ€ngigkeiten aktualisieren
+
+Jetzt werden wir unsere AbhĂ€ngigkeiten aktualisieren.
+
+Wir möchten den `current_user` *nur* erhalten, wenn dieser Benutzer aktiv ist.
+
+Daher erstellen wir eine zusĂ€tzliche AbhĂ€ngigkeit `get_current_active_user`, die wiederum `get_current_user` als AbhĂ€ngigkeit verwendet.
+
+Beide AbhĂ€ngigkeiten geben nur dann einen HTTP-Error zurĂŒck, wenn der Benutzer nicht existiert oder inaktiv ist.
+
+In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer existiert, korrekt authentifiziert wurde und aktiv ist:
+
+=== "Python 3.10+"
+
+    ```Python hl_lines="58-66  69-74  94"
+    {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+    ```
+
+=== "Python 3.9+"
+
+    ```Python hl_lines="58-66  69-74  94"
+    {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+    ```
+
+=== "Python 3.8+"
+
+    ```Python hl_lines="59-67  70-75  95"
+    {!> ../../../docs_src/security/tutorial003_an.py!}
+    ```
+
+=== "Python 3.10+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="56-64  67-70  88"
+    {!> ../../../docs_src/security/tutorial003_py310.py!}
+    ```
+
+=== "Python 3.8+ nicht annotiert"
+
+    !!! tip "Tipp"
+        Bevorzugen Sie die `Annotated`-Version, falls möglich.
+
+    ```Python hl_lines="58-66  69-72  90"
+    {!> ../../../docs_src/security/tutorial003.py!}
+    ```
+
+!!! info
+    Der zusĂ€tzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurĂŒckgeben, ist ebenfalls Teil der Spezifikation.
+
+    Jeder HTTP-(Fehler-)Statuscode 401 â€žUNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurĂŒckgeben.
+
+    Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten.
+
+    Sie können diesen zusĂ€tzlichen Header tatsĂ€chlich weglassen und es wĂŒrde trotzdem funktionieren.
+
+    Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen.
+
+    Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte fĂŒr Sie oder Ihre Benutzer jetzt oder in der Zukunft nĂŒtzlich sein.
+
+    Das ist der Vorteil von Standards ...
+
+## Es in Aktion sehen
+
+Öffnen Sie die interaktive Dokumentation: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+
+### Authentifizieren
+
+Klicken Sie auf den Button â€žAuthorize“.
+
+Verwenden Sie die Anmeldedaten:
+
+Benutzer: `johndoe`
+
+Passwort: `secret`.
+
+<img src="/img/tutorial/security/image04.png">
+
+Nach der Authentifizierung im System sehen Sie Folgendes:
+
+<img src="/img/tutorial/security/image05.png">
+
+### Die eigenen Benutzerdaten ansehen
+
+Verwenden Sie nun die Operation `GET` mit dem Pfad `/users/me`.
+
+Sie erhalten Ihre Benutzerdaten:
+
+```JSON
+{
+  "username": "johndoe",
+  "email": "johndoe@example.com",
+  "full_name": "John Doe",
+  "disabled": false,
+  "hashed_password": "fakehashedsecret"
+}
+```
+
+<img src="/img/tutorial/security/image06.png">
+
+Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen Vorgang nochmal versuchen, erhalten Sie einen HTTP 401 Error:
+
+```JSON
+{
+  "detail": "Not authenticated"
+}
+```
+
+### Inaktiver Benutzer
+
+Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit:
+
+Benutzer: `alice`.
+
+Passwort: `secret2`.
+
+Und versuchen Sie, die Operation `GET` mit dem Pfad `/users/me` zu verwenden.
+
+Sie erhalten die Fehlermeldung â€žInactive user“:
+
+```JSON
+{
+  "detail": "Inactive user"
+}
+```
+
+## Zusammenfassung
+
+Sie verfĂŒgen jetzt ĂŒber die Tools, um ein vollstĂ€ndiges Sicherheitssystem basierend auf `username` und `password` fĂŒr Ihre API zu implementieren.
+
+Mit diesen Tools können Sie das Sicherheitssystem mit jeder Datenbank und jedem Benutzer oder Datenmodell kompatibel machen.
+
+Das einzige fehlende Detail ist, dass es noch nicht wirklich â€žsicher“ ist.
+
+Im nĂ€chsten Kapitel erfahren Sie, wie Sie eine sichere Passwort-Hashing-Bibliothek und <abbr title="JSON Web Tokens">JWT</abbr>-Token verwenden.