Nachdem ich die zustandslose JWT-Authentifizierung (hier verfügbar) eingerichtet hatte, wollte ich verstehen, was unter den Abstraktionen von Spring Security passiert, indem ich Schlüsselkomponenten und ihre Interaktionen identifizierte. Um diese Erkundung spannender zu gestalten, habe ich mithilfe der Standard-HTTP-Bibliothek eine Minimalversion in Go neu implementiert. Indem ich drei Kernabläufe – Registrierung, Token-Generierung und Zugriff auf geschützte Ressourcen – aufschlüsselte und sie in Go neu aufbaute, wollte ich die Authentifizierungsmuster von Spring Security einfacheren Komponenten zuordnen.
Dieser Beitrag konzentriert sich speziell auf Authentifizierungsabläufe – wie das System die Benutzeridentität überprüft – und nicht auf die Autorisierung. Wir werden die Abläufe mit Sequenzdiagrammen untersuchen, die Anforderungen durch verschiedene Komponenten in der Architektur von Spring Security verfolgen.
Das System stellt drei Endpunkte bereit:
In den folgenden Abschnitten erkläre ich die Kernkomponenten jedes Ablaufs mit einem Sequenzdiagramm für jeden.
Eine Registrierungsanfrage mit Benutzername und Passwort durchläuft die Spring Security-Filterkette, wo nur minimale Verarbeitung erfolgt, da der Registrierungsendpunkt in SecurityConfiguration so konfiguriert wurde, dass keine Authentifizierung erforderlich ist. Die Anfrage wird dann durch das DispatcherServlet von Spring geleitet, das sie basierend auf dem URL-Muster an die entsprechende Methode in UserController weiterleitet. Die Anfrage erreicht den Registerendpunkt des UserControllers, wo die Benutzerinformationen zusammen mit einem gehashten Passwort gespeichert werden.
Eine Anmeldeanforderung mit Benutzername und Passwort durchläuft die Spring Security-Filterkette, wo nur minimale Verarbeitung erfolgt, da dieser Endpunkt auch so konfiguriert ist, dass in SecurityConfiguration keine Authentifizierung erforderlich ist. Die Anfrage wird über das DispatcherServlet von Spring an den Anmeldeendpunkt von UserController weitergeleitet, der an AuthenticationManager delegiert. Mithilfe der in ApplicationConfiguration definierten konfigurierten Beans überprüft AuthenticationManager die bereitgestellten Anmeldeinformationen anhand der gespeicherten. Nach erfolgreicher Authentifizierung generiert der UserController mithilfe von JwtService ein JWT-Token mit den Benutzerinformationen und Metadaten wie der Erstellungszeit, das für nachfolgende authentifizierte Anforderungen an den Client zurückgegeben wird.
Wenn eine Anfrage eintrifft, die ein JWT-Token im Authorization-Header enthält, durchläuft sie den JwtAuthenticationFilter – einen benutzerdefinierten OncePerRequestFilter – der das Token mithilfe von JwtService verarbeitet. Wenn gültig, ruft der Filter den Benutzer über den in ApplicationConfiguration konfigurierten UserDetailsService ab und legt die Authentifizierung in SecurityContextHolder fest. Wenn das Token fehlt oder ungültig ist, lässt der Filter zu, dass die Anfrage fortgesetzt wird, ohne dass die Authentifizierung festgelegt wird.
Später in der Kette prüft AuthorizationFilter, ob die Anfrage ordnungsgemäß über SecurityContextHolder authentifiziert ist. Wenn eine fehlende Authentifizierung festgestellt wird, wird eine AccessDeniedException ausgelöst. Diese Ausnahme wird von ExceptionTranslationFilter abgefangen, der prüft, ob der Benutzer anonym ist, und an den konfigurierten JwtAuthenticationEntryPoint in SecurityConfiguration delegiert, um eine 401 Unauthorized-Antwort zurückzugeben.
Wenn alle Filter erfolgreich sind, erreicht die Anfrage das DispatcherServlet von Spring, das sie an den getAuthenticatedUser-Endpunkt in UserController weiterleitet. Dieser Endpunkt ruft die authentifizierten Benutzerinformationen von SecurityContextHolder ab, die während des Filterkettenprozesses ausgefüllt wurden.
Hinweis: Spring Security nutzt ein umfangreiches Ökosystem aus Filtern und spezialisierten Komponenten, um verschiedene Sicherheitsbedenken zu bewältigen. Um den Kernauthentifizierungsablauf zu verstehen, habe ich mich nur auf die Hauptakteure bei der JWT-Token-Validierung und Benutzerauthentifizierung konzentriert.
Die Go-Implementierung bietet ähnliche Funktionalität durch eine vereinfachte Architektur, die den wichtigsten Spring Security-Komponenten zugeordnet ist:
FilterChain
Disponent
Authentifizierungskontext
JwtFilter
AuthentifizierungsFilter
JwtService
Beide Implementierungen umfassen Integrationstests (auth_test.go und AuthTest.java), die wichtige Authentifizierungsszenarien überprüfen:
Registrierungsablauf
Anmeldeablauf
Geschützter Ressourcenzugriff
Die Java-Implementierung enthält detaillierte Kommentare, die den Ablauf jedes Testszenarios durch die Filterkette von Spring Security erläutern. Dieselben Abläufe werden in der Go-Implementierung unter Verwendung gleichwertiger Komponenten repliziert.
Ich habe mir die JWT-Authentifizierung von Spring Security angesehen, indem ich sie in Flows und Testfälle unterteilt habe. Dann habe ich diese Muster Go-Komponenten zugeordnet. Integrationstests zeigten mir, wie Anfragen durch die Filterkette und Komponenten von Spring Security fließen. Das Erstellen einfacher Versionen dieser Muster hat mir geholfen, das Design von Spring Security zu verstehen. Die Tests haben gezeigt, dass beide Implementierungen die Authentifizierung auf die gleiche Weise handhaben. Durch das Analysieren, Testen und Neuaufbauen habe ich ein tieferes Verständnis dafür gewonnen, wie die Authentifizierung von Spring Security funktioniert.
Das obige ist der detaillierte Inhalt vonGrundlegendes zur JWT-Authentifizierung: Architektur und Go-Implementierung von Spring Security. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!