Steuern Sie die Sitzung mit Spring Security

1. Übersicht

In diesem Artikel werden wir veranschaulichen, wie Spring Security es uns ermöglicht, unsere HTTP-Sitzungen zu steuern .

Dieses Steuerelement reicht von einem Sitzungszeitlimit bis zum Aktivieren gleichzeitiger Sitzungen und anderer erweiterter Sicherheitskonfigurationen.

2. Wann wird die Sitzung erstellt?

Wir können genau steuern, wann unsere Sitzung erstellt wird und wie Spring Security damit interagiert:

  • Immer - Eine Sitzung wird immer erstellt, wenn noch keine vorhanden ist
  • ifRequired - Eine Sitzung wird nur bei Bedarf erstellt ( Standard )
  • Niemals - Das Framework erstellt niemals eine Sitzung selbst, verwendet jedoch eine, wenn diese bereits vorhanden ist
  • zustandslos - Spring Security wird keine Sitzung erstellen oder verwenden
...

Java-Konfiguration:

@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) }

Es ist sehr wichtig zu verstehen, dass diese Konfiguration nur die Funktionen von Spring Security steuert - nicht die gesamte Anwendung. Spring Security erstellt die Sitzung möglicherweise nicht, wenn wir dies nicht anweisen, aber unsere App kann dies tun!

Standardmäßig erstellt Spring Security eine Sitzung, wenn eine benötigt wird - dies ist „ ifRequired “.

Bei einer zustandsloseren Anwendung stellt die Option " Nie " sicher, dass Spring Security selbst keine Sitzung erstellt. Wenn die Anwendung jedoch eine erstellt, verwendet Spring Security diese.

Schließlich ist die strengste Option zur Sitzungserstellung - " zustandslos " - eine Garantie dafür, dass die Anwendung überhaupt keine Sitzung erstellt .

Dies wurde in Spring 3.1 eingeführt und überspringt effektiv Teile der Spring Security-Filterkette - hauptsächlich die sitzungsbezogenen Teile wie HttpSessionSecurityContextRepository , SessionManagementFilter , RequestCacheFilter .

Diese strengeren Kontrollmechanismen haben die direkte Folge, dass keine Cookies verwendet werden und daher jede einzelne Anforderung erneut authentifiziert werden muss . Diese zustandslose Architektur spielt gut mit REST-APIs und ihrer Einschränkung der Statuslosigkeit. Sie funktionieren auch gut mit Authentifizierungsmechanismen wie Basic- und Digest-Authentifizierung.

3. Unter der Haube

Vor dem Ausführen des Authentifizierungsprozesses führt Spring Security einen Filter aus, der für das Speichern des Sicherheitskontexts zwischen Anforderungen verantwortlich ist - den SecurityContextPersistenceFilter . Der Kontext wird gemäß einer Strategie gespeichert - standardmäßig HttpSessionSecurityContextRepository - die die HTTP-Sitzung als Speicher verwendet.

Für das strikte Attribut create-session = "stateless" wird diese Strategie durch eine andere ersetzt - NullSecurityContextRepository - und es wird keine Sitzung erstellt oder verwendet , um den Kontext beizubehalten .

4. Gleichzeitige Sitzungssteuerung

Wenn ein bereits authentifizierter Benutzer versucht, sich erneut zu authentifizieren , kann die Anwendung dieses Ereignis auf verschiedene Arten behandeln. Es kann entweder die aktive Sitzung des Benutzers ungültig machen und den Benutzer erneut mit einer neuen Sitzung authentifizieren oder beide Sitzungen gleichzeitig zulassen.

Der erste Schritt zum Aktivieren der gleichzeitigen Unterstützung der Sitzungssteuerung besteht darin, der web.xml den folgenden Listener hinzuzufügen :

  org.springframework.security.web.session.HttpSessionEventPublisher  

Oder definieren Sie es als Bean - wie folgt:

@Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); }

Dies ist wichtig, um sicherzustellen, dass die Spring Security-Sitzungsregistrierung benachrichtigt wird, wenn die Sitzung zerstört wird .

Um das Szenario zu aktivieren, das mehrere gleichzeitige Sitzungen für denselben Benutzer ermöglicht, wird die Element sollte in der XML-Konfiguration verwendet werden:

Oder über die Java-Konfiguration:

@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement().maximumSessions(2) }

5. Sitzungszeitlimit

5.1. Behandlung des Sitzungszeitlimits

Wenn der Benutzer nach Ablauf der Sitzung eine Anforderung mit einer abgelaufenen Sitzungs-ID sendet , wird er zu einer URL umgeleitet, die über den Namespace konfiguriert werden kann:

Wenn der Benutzer eine Anfrage mit einer Sitzungs-ID sendet, die nicht abgelaufen, aber vollständig ungültig ist , wird er ebenfalls an eine konfigurierbare URL umgeleitet:

 ... 

Die entsprechende Java-Konfiguration:

http.sessionManagement() .expiredUrl("/sessionExpired.html") .invalidSessionUrl("/invalidSession.html");

5.2. Konfigurieren Sie das Sitzungszeitlimit mit Spring Boot

Wir können den Sitzungszeitlimitwert des eingebetteten Servers mithilfe der folgenden Eigenschaften einfach konfigurieren:

server.servlet.session.timeout=15m

Wenn wir die Dauereinheit nicht angeben, geht Spring von Sekunden aus.

Kurz gesagt, mit dieser Konfiguration läuft die Sitzung nach 15 Minuten Inaktivität ab. Die Sitzung nach diesem Zeitraum wird als ungültig angesehen.

Wenn wir unser Projekt für die Verwendung von Tomcat konfiguriert haben, müssen wir berücksichtigen, dass es nur die Minutengenauigkeit für das Sitzungszeitlimit mit mindestens einer Minute unterstützt. Dies bedeutet, dass wenn wir beispielsweise einen Timeout-Wert von 170s angeben, dies zu einem Timeout von 2 Minuten führt.

Schließlich ist es wichtig zu erwähnen, dass, obwohl Spring Session eine ähnliche Eigenschaft für diesen Zweck unterstützt ( spring.session.timeout ), die Autokonfiguration auf den Wert der zuerst erwähnten Eigenschaft zurückgreift , wenn dies nicht angegeben ist.

6. Verhindern Sie die Verwendung von URL-Parametern für die Sitzungsverfolgung

Das Offenlegen von Sitzungsinformationen in der URL stellt ein wachsendes Sicherheitsrisiko dar (von Platz 7 im Jahr 2007 bis Platz 2 im Jahr 2013 in der OWASP-Top-10-Liste).

Ab Spring 3.0 kann die URL-Umschreibungslogik, mit der die jsessionid an die URL angehängt wird , jetzt deaktiviert werden, indem disable-url-rewriting = "true" in der URL festgelegt wird Namespace.

Alternativ kann der Sitzungsverfolgungsmechanismus ab Servlet 3.0 auch in der Datei web.xml konfiguriert werden :

 COOKIE 

Und programmatisch:

servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));

Hiermit wird festgelegt, wo die JSESSIONID gespeichert werden soll - im Cookie oder in einem URL-Parameter.

7. Sitzungsfixierungsschutz mit Spring Security

Das Framework bietet Schutz vor typischen Angriffen zur Sitzungsfixierung, indem konfiguriert wird, was mit einer vorhandenen Sitzung passiert, wenn der Benutzer erneut versucht, sich zu authentifizieren:

 ...

Die entsprechende Java-Konfiguration:

http.sessionManagement() .sessionFixation().migrateSession()

Standardmäßig ist dieser Schutz in Spring Security aktiviert („ migrateSession “). Bei der Authentifizierung wird eine neue HTTP-Sitzung erstellt, die alte wird ungültig und die Attribute der alten Sitzung werden kopiert.

Wenn dies nicht das gewünschte Verhalten ist, stehen zwei weitere Optionen zur Verfügung:

  • Wenn " keine " festgelegt ist, wird die ursprüngliche Sitzung nicht ungültig
  • when “newSession” is set, a clean session will be created without any of the attributes from the old session being copied over

8. Secure Session Cookie

Next, we'll discuss how to secure our session cookie.

We can use the httpOnly and secure flags to secure our session cookie:

  • httpOnly: if true then browser script won't be able to access the cookie
  • secure: if true then the cookie will be sent only over HTTPS connection

We can set those flags for our session cookie in the web.xml:

 1  true true  

This configuration option is available since Java servlet 3. By default, http-only is true and secure is false.

Let's also have a look at the corresponding Java configuration:

public class MainWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext sc) throws ServletException { // ... sc.getSessionCookieConfig().setHttpOnly(true); sc.getSessionCookieConfig().setSecure(true); } }

If we're using Spring Boot, we can set these flags in our application.properties:

server.servlet.session.cookie.http-only=true server.servlet.session.cookie.secure=true

Finally, we can also achieve this manually by using a Filter:

public class SessionFilter implements Filter { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; Cookie[] allCookies = req.getCookies(); if (allCookies != null) { Cookie session = Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID")) .findFirst().orElse(null); if (session != null) { session.setHttpOnly(true); session.setSecure(true); res.addCookie(session); } } chain.doFilter(req, res); } }

9. Working With the Session

9.1. Session Scoped Beans

A bean can be defined with session scope simply by using the @Scope annotation on beans declared in the web-Context:

@Component @Scope("session") public class Foo { .. }

Or with XML:

Then, the bean can simply be injected into another bean:

@Autowired private Foo theFoo;

And Spring will bind the new bean to the lifecycle of the HTTP Session.

9.2. Injecting the Raw Session into a Controller

The raw HTTP Session can also be injected directly into a Controller method:

@RequestMapping(..) public void fooMethod(HttpSession session) { session.setAttribute(Constants.FOO, new Foo()); //... Foo foo = (Foo) session.getAttribute(Constants.FOO); }

9.3. Obtaining the Raw Session

Die aktuelle HTTP-Sitzung kann auch programmgesteuert über die Raw-Servlet-API abgerufen werden :

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true); // true == allow create

10. Schlussfolgerung

In diesem Artikel haben wir die Verwaltung von Sitzungen mit Spring Security erläutert. Außerdem enthält die Spring-Referenz eine sehr gute FAQ zur Sitzungsverwaltung.

Wie immer ist der in diesem Artikel vorgestellte Code auf Github verfügbar. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.