Start / Seminare / FastAPI Architektur in der Praxis

Modul

Saubere Grenzen, Autorisierung und Test

4 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Grenzen, Autorisierung und Test

0:00 Der Abhängigkeitsgraph aus dem letzten Modul funktioniert — aber er ist noch nicht schön. Die Handler tragen ihre Verdrahtung sichtbar mit sich herum, und vor allem prüft bisher niemand, wer da eigentlich ruft. Beides holen wir in diesem Modul nach. Und am Ende kommt etwas heraus, das wir gar nicht eigens gebaut haben: Testbarkeit. Sie fällt aus der Art, wie der Graph komponiert ist, einfach ab.

0:23 Das ist übrigens ein gutes Erkennungszeichen für tragfähige Architektur — die nützlichen Eigenschaften ergeben sich, statt dass man sie nachträglich einbaut.

Annotierte Aliase für klare Grenzen

0:33 Fangen wir mit dem Aufräumen an. Schauen Sie sich eine Handler-Signatur aus dem letzten Modul an: Da steht der Typ, da steht der Provider, da steht das Schlüsselwort dazwischen — und das in jedem einzelnen Endpunkt aufs Neue. Das ist nicht falsch, aber es verstellt den Blick. Die Signatur soll sagen, was der Endpunkt braucht, nicht wie es zusammengebaut wird.

0:54 Die Idee ist ein Kürzel mit Bedeutung. Sie geben der Kombination aus Typ und Verdrahtung einen Namen und benutzen ab dann nur noch diesen Namen. Was technisch eine Abkürzung ist, wird dadurch zu einer Aussage: Jeder dieser Namen benennt eine Grenze in Ihrer Architektur — hier endet der Webteil, hier beginnt der Service.

1:12 Denken Sie an die Türschilder in einem Gebäude. Sie sparen keine Wege, aber sie machen aus einem Gang mit vielen Türen ein Haus mit Abteilungen. Und sie stehen jeweils an genau einer Tür. Worauf es hier ankommt: Der obere Teil wird einmal geschrieben, der untere beliebig oft. Und der untere liest sich jetzt wie eine Anforderungsliste — dieser Endpunkt braucht einen Angebotsservice, fertig.

1:35 Wie der entsteht, wer ihm die Session gibt, woher die Kennung der Anfrage kommt: alles nicht mehr sichtbar, weil es hier auch nicht hingehört. Wenn Sie später einen Provider austauschen, ändern Sie die obere Zeile, und sämtliche Endpunkte ziehen mit, ohne dass eine einzige Signatur angefasst werden müsste. Der letzte Punkt ist der, den man erst beim Testen zu schätzen weiß. Die Tests brauchen nämlich genau dieselben Provider-Funktionen wie die Router — sie müssen sie ersetzen können.

2:02 Liegen die alle in einem Modul beieinander, importieren Tests aus derselben Quelle wie der Produktivcode, und es gibt keine zweite Wahrheit. Das klingt nach einer Kleinigkeit und ist der Grund dafür, dass das vierte Kapitel dieses Moduls so kurz ausfällt: Wir müssen zum Testen nichts Neues bauen, weil die Anschlüsse schon da sind.

2:20 Der erste Punkt ist eine Verwechslung, die beim Umstellen fast jedem einmal passiert. Der Alias ist ein Typ — er gehört an die Stelle, wo sonst der Typ steht. Er ist kein Aufruf, der zusätzlich zum Typ dazukommt. Schreibt man beides hin, weil man den alten Code halb umgestellt hat, wird die Dependency doppelt aufgelöst, und die Fehlermeldung ist wenig hilfreich.

2:41 Und der letzte Punkt ist einfach Hygiene: Nach dem Umstellen sind eine Reihe von Importen überflüssig. Die stehen zu lassen ist harmlos, aber sie erzählen dem nächsten Leser eine Geschichte, die nicht mehr stimmt.

Rollenwächter an der Route

2:54 Jetzt zur zweiten offenen Flanke, und die ist ernster als die erste: Bisher darf jeder alles. Es gibt keinen einzigen Endpunkt in unserer Anwendung, der prüft, wer da eigentlich ruft. Jeder könnte jedes Angebot freigeben. Das ändern wir — und zwar mit genau dem Werkzeug, das wir schon kennen. Autorisierung ist in FastAPI nichts Besonderes, sondern auch nur eine Dependency.

3:17 Das ist die gute Nachricht dieses Kapitels, und sie erspart uns eine Menge Sonderbehandlung. Hier steckt eine kleine Denkfigur drin, die es wert ist, sie einmal langsam anzuschauen. Wir schreiben nicht einen Wächter, sondern eine Funktion, die Wächter herstellt. Sie sagt ihr, welche Rollen erlaubt sind, und bekommt einen passenden Wächter zurück.

3:38 Wie bei einem Schlüsseldienst: Sie bestellen keinen fertigen Schlüssel, Sie geben das Schloss an und bekommen den dazu passenden. Der Vorteil ist, dass Sie nicht für jede Rollenkombination eine eigene Funktion schreiben müssen. Eine Fabrik, beliebig viele Wächter. Zwei Ebenen, und die innere ist die eigentliche Dependency. Sie erklärt in ihrer Signatur, dass sie den aktuellen Benutzer braucht — auch das wieder ganz normal über den Graphen.

4:04 Dann vergleicht sie die Rollen und wirft im Zweifelsfall den Verbotscode. Worauf es ankommt, steht nicht im Code, sondern in der Fußzeile: Das passiert, bevor der Handlerkörper überhaupt anläuft. Der abgewiesene Aufrufer berührt Ihre Fachlogik nie. Das ist ein deutlicher Unterschied zu einer Prüfung in der ersten Zeile des Handlers — dort ist er schon drin.

4:26 Der Unterschied zwischen den ersten beiden Zeilen ist praktischer Natur. Manchmal wollen Sie nur die Tür bewachen und interessieren sich nicht dafür, wer hereinkommt — dann reicht die Torwächter-Variante, und ihr Rückgabewert wird schlicht weggeworfen. Manchmal braucht der Handler den Benutzer aber selbst, etwa um dessen Niederlassung zu vergleichen. Dann nehmen Sie ihn als Parameter.

4:47 Und die unteren beiden Zeilen zeigen die Hebelwirkung: Dieselbe Prüfung lässt sich an einen ganzen Router hängen. Eine Zeile statt zwanzig, und neue Endpunkte sind automatisch geschützt. Diese fünf Schritte haben einen Bruch in der Mitte, und der ist beabsichtigt. Die ersten beiden richten die grobe Grenze ein: Wer nicht Disposition oder kaufmännische Leitung ist, kommt gar nicht erst durch. Ab dem dritten Schritt wird es feiner.

5:12 Der Vertrieb darf grundsätzlich Angebote sehen — aber nur die der eigenen Niederlassung. Diese Regel kann kein Türsteher entscheiden, denn sie hängt vom einzelnen Angebot ab. Deshalb wandert sie in den Handler, wo die Daten vorliegen. Zwei verschiedene Fragen, zwei verschiedene Orte. Der Kern dieser Aufgabe ist ein Unterschied, den man sauber benennen können sollte.

5:34 Dieselbe Person, dieselbe Rolle, zwei verschiedene Angebote — und einmal geht es und einmal nicht. Das kann keine Rollenliste leisten, denn die Rolle ist ja in beiden Fällen dieselbe. Was den Ausschlag gibt, sind Daten: die Niederlassung des Benutzers gegen die des Veranstalters. Wenn Sie am Ende beide Fälle vorführen können und dabei erklären, warum die Prüfung nicht ans Tor gehört, haben Sie den Punkt des Kapitels.

Autorisierung über Rollenlisten hinaus

5:58 Unsere Wächter tun ihren Dienst. Bevor wir das Thema verlassen, treten wir aber einen Schritt zurück. Autorisierung hat nämlich mehr Dimensionen als eine Rollenliste, und ein paar davon lohnt es sich zu kennen, bevor man sie schmerzhaft selbst entdeckt. Es geht um drei Fragen: welcher Statuscode, welches Modell, und an welcher Stelle die Prüfung hängt.

6:19 Die beiden Statuscodes werden ständig verwechselt, dabei beantworten sie ganz verschiedene Fragen. Der eine sagt: Ich weiß nicht, wer du bist — zeig mir deinen Ausweis. Der andere sagt: Ich weiß genau, wer du bist, und du darfst das trotzdem nicht. Für den Aufrufer ist das ein erheblicher Unterschied. Beim ersten hilft ein neues Anmelden, beim zweiten ist ein neues Anmelden sinnlos.

6:42 In unserer Anwendung ist es immer der zweite Fall, weil die Identität sich bei uns immer sauber auflöst und nur die Rollenprüfung scheitert. Die entscheidende Zeile ist die oberste: zwei verschiedene Fragen. Rollen fragen, wer Sie sind — das ist eine Eigenschaft der Person und ändert sich selten. Attribute fragen, was für diesen konkreten Fall gilt — das hängt an den Daten und kann bei jedem Datensatz anders ausfallen.

7:07 In der Fußnote steht, wie es in der Praxis meist läuft: erst grob über Rollen, dann fein über Attribute. Das ist kein Kompromiss, sondern sinnvoll. Die grobe Prüfung ist billig und schützt den Handler, die feine braucht ohnehin die geladenen Daten. Das Warnsignal im ersten Punkt sollten Sie sich merken, es ist sehr zuverlässig.

7:27 Sobald Sie anfangen, Rollen mit Bindestrichen zusammenzusetzen — Vertrieb, Niederlassung Nord, nur lesend —, kodieren Sie in Wahrheit Attribute und Rechte in einen Namen hinein. Die Zahl solcher Rollen wächst dann multiplikativ, und irgendwann verwaltet niemand mehr, wer welche hat. Der Ausweg ist eine Ebene dazwischen: Rollen gewähren Rechte, und die Wächter prüfen Rechte statt Rollen. Danach lässt sich umsortieren, ohne einen einzigen Wächter anzufassen.

7:54 Die Bauform bleibt dabei genau dieselbe. Hier ist Ehrlichkeit angebracht: Unsere Identität kommt aus Kopfzeilen der Anfrage. Das heißt, jeder kann behaupten, die kaufmännische Leitung zu sein. Für eine Demonstration ist das ideal, weil man Rollen mit einem Kommandozeilenaufruf durchprobieren kann. Als Authentifizierung ist es wertlos.

8:15 Produktiv steht dort ein signiertes Token, und entscheidend ist das Wort geprüft: Signatur und Ablaufdatum. Ein bloß dekodiertes Token ist eine Zeichenkette, die jeder selbst schreiben kann. Der wichtige Punkt für uns ist aber, dass die Form der Funktion dabei gleich bleibt — nur ihr Innenleben ändert sich.

Den Graphen testen

8:34 Kommen wir zu dem Versprechen, das im letzten Modul mehrfach gefallen ist: Jeder Knoten dieses Graphen ist einzeln prüfbar. Jetzt lösen wir es ein. Das Bemerkenswerte daran ist, dass wir dafür nichts Neues bauen müssen — keine Testbibliothek, keine besondere Vorkehrung im Produktivcode. Dieselben Nähte, die die Anwendung zusammensetzen, benutzen die Tests, um sie wieder auseinanderzunehmen.

8:57 Das ist kein Zufall, sondern die eigentliche Rendite der letzten beiden Kapitel. Die Überlegung dahinter ist es wert, sie sich einzuprägen: Ein Test ersetzt fast immer die Ränder, nicht die Mitte. Die Ränder sind die Datenbank und die Identität des Aufrufers — beides Dinge, die man im Test nicht echt haben will. Die Mitte ist Ihre Fachlogik, und die soll echt laufen, denn sie ist ja der Prüfgegenstand.

9:21 FastAPI bietet dafür eine Zuordnung an: Sie sagen, diese Provider-Funktion wird im Test durch jene ersetzt, und alle Endpunkte, die davon abhingen, bekommen still den Ersatz. Zwei Ersetzungen, und beide zeigen dasselbe Muster. Die eine baut die Session aus einer Testfabrik statt aus der echten. Die andere liefert einfach eine Person zurück — eine kaufmännische Leitung, ohne Anmeldung, ohne Token, ohne irgendetwas.

9:46 Der Schlüssel dieser Zuordnung ist übrigens die Provider-Funktion selbst, nicht ihr Name als Zeichenkette. Deshalb zahlt sich das Providermodul aus dem ersten Kapitel jetzt ein zweites Mal aus: Test und Router beziehen dieselbe Funktion aus derselben Quelle, und ein Tippfehler ist gar nicht möglich. Achten Sie auf den zweiten Punkt — was hier alles nicht nötig ist.

10:07 Kein nachträgliches Überschreiben von Modulinhalten, keine Importtricks, und vor allem: keine Testschalter im Produktivcode. Solche Schalter sind ein verbreitetes Übel, weil sie eine Anwendung erzeugen, die im Test anders läuft als im Betrieb — und damit genau die Aussagekraft zerstören, für die man Tests schreibt. Hier gibt es nichts dergleichen. Die Anwendung weiß gar nicht, dass sie getestet wird. Sie bekommt nur an einer definierten Stelle etwas anderes gereicht.

10:35 Der zweite Punkt ist eine Diagnose, die weit über das Testen hinausgeht. Wenn sich ein Teil Ihrer Anwendung partout nicht prüfen lässt, dann liegt das selten am Testwerkzeug. Meistens schleicht sich dort eine Ressource am Graphen vorbei herein — ein Modulimport, eine globale Variable, ein Client, der sich selbst konfiguriert.

10:54 Behandeln Sie das nicht als Testproblem, sondern als Hinweis auf die Architektur. Und der erste Punkt ist schlicht Hygiene: Diese Ersetzungen hängen global an der Anwendung. Räumen Sie sie zwischen den Tests auf, sonst beeinflussen sie einander. Diese Aufgabe zeigt, was der ganze Aufwand wert ist. Zwei Tests, die sich in genau einer Sache unterscheiden — der Rolle der Person, die ruft.

11:18 Einmal kommt der Verbotscode, einmal geht die Anfrage durch. Und das Bemerkenswerte: Sie brauchen dafür keinen Identitätsanbieter, kein Token, keine Anmeldung. Nur zwei kleine Funktionen, die je eine Person zurückgeben. Sicherheitsregeln gehören zu den Dingen, die am seltensten getestet werden, weil es meist so mühsam ist.

11:38 Wenn es zwei Zeilen kostet, gibt es dafür keine Ausrede mehr.

Was jetzt trägt

11:43 Damit sind die Grenzen gezogen und bewacht. Jeder Alias benennt eine Grenze an genau einer Stelle. Die Autorisierung ist eine Dependency und greift vor dem Handler. Rollen ziehen die grobe Linie, Attribute entscheiden den Einzelfall. Und die Testbarkeit ist abgefallen, ohne dass wir sie eigens gebaut hätten. Was jetzt noch fehlt, ist der Umgang mit dem, was gleichzeitig passiert: mehrere Aufgaben auf einmal, ein Live-Fortschritt für die Disposition und die Frage, was mit geteiltem Zustand geschieht, wenn mehrere Prozesse laufen.

12:13 Das ist das letzte Modul.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →