Meine Firma hat Spring MVC evaluiert, um festzustellen, ob wir es in einem unserer nächsten Projekte verwenden sollten. Bisher liebe ich, was ich gesehen habe, und jetzt schaue ich mir das Spring Security-Modul an, um festzustellen, ob wir etwas verwenden können/sollten.Komponententests mit Spring Security
Unsere Sicherheitsanforderungen sind ziemlich einfach; Ein Benutzer muss lediglich einen Benutzernamen und ein Passwort angeben können, um auf bestimmte Teile der Website zugreifen zu können (z. B. um Informationen über sein Konto zu erhalten). und es gibt eine Handvoll Seiten auf der Seite (FAQs, Support, usw.), wo ein anonymer Benutzer Zugang erhalten soll.
In dem Prototyp, den ich erstellt habe, habe ich ein "LoginCredentials" -Objekt (das nur Benutzername und Passwort enthält) in der Sitzung für einen authentifizierten Benutzer gespeichert; Einige der Controller überprüfen, ob dieses Objekt in der Sitzung ist, um beispielsweise einen Verweis auf den angemeldeten Benutzernamen zu erhalten. Ich möchte stattdessen diese hauseigene Logik durch Spring Security ersetzen, was den Vorteil hätte, jede Art von "Wie verfolgen wir eingeloggte Benutzer?" Zu entfernen. und "Wie authentifizieren wir Benutzer?" von meinem Controller/Geschäftscode.
Es scheint, wie Spring Security bietet eine (pro Thread) „Kontext“ Objekt der Lage sein, den Benutzernamen/Hauptinfo in Ihrer Anwendung von überall zugreifen ...
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
... das scheint sehr un-Frühling wie dieses Objekt ein (globaler) Singleton ist, in gewisser Weise.
Meine Frage ist dies: Wenn dies die Standardmethode ist, um auf Informationen über den authentifizierten Benutzer in Spring Security zuzugreifen, was ist die akzeptierte Methode, ein Authentication Objekt in den SecurityContext zu injizieren, damit es für meine Unit Tests verfügbar ist Komponententests erfordern einen authentifizierten Benutzer?
Muss ich dies bei der Initialisierung jedes Testfalls verdrahten?
protected void setUp() throws Exception {
...
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(testUser.getLogin(), testUser.getPassword()));
...
}
Dies scheint übermäßig ausführlich. Gibt es einen leichteren Weg?
Das SecurityContextHolder
Objekt selbst scheint sehr un-Spring-like ...
Danke, das ist ein nützlicher Rat. Was ich bisher gemacht habe, ist im Wesentlichen, mit dem Aufruf von SecurityContextHolder.getContext() fortzufahren (durch ein paar eigene Wrapper-Methoden, so dass es zumindest von einer Klasse aufgerufen wird). –
Obwohl nur eine Anmerkung - ich glaube nicht, ServletContextHolder hat ein Konzept von HttpSession oder eine Möglichkeit zu wissen, ob es in einer Web-Server-Umgebung funktioniert - es verwendet ThreadLocal, wenn Sie es für etwas anderes konfigurieren (die einzigen anderen zwei eingebauten Modi sind) InheritableThreadLocal und Global) –
Der einzige Nachteil bei der Verwendung von session/request-scoped Beans im Frühling ist, dass sie in einem JUnit-Test fehlschlagen. Was Sie tun können, ist ein benutzerdefinierter Bereich zu implementieren, der Sitzung/Anfrage verwendet, falls verfügbar, und auf den Thread zurückfallen muss. Meine Vermutung ist, dass Spring Security etwas Ähnliches macht ... –