Kontrollieren Sie die Sitzung mit Spring Security

Steuern Sie die Sitzung mit Spring Security

1. Überblick

In diesem Artikel werden wir veranschaulichen, wieSpring Security allows us to control our HTTP Sessions.

Dieses Steuerelement reicht von einem Sitzungszeitlimit bis zur Aktivierung von gleichzeitigen Sitzungen und anderen erweiterten Sicherheitskonfigurationen.

Weitere Lektüre:

Abrufen von Benutzerinformationen in Spring Security

So erhalten Sie den aktuell angemeldeten Benutzer mit Spring Security.

Read more

Spring Security Angemeldet bleiben

Cookie Remember Me Beispiel mit Spring Security.

Read more

Spring Security Logout

Spring Logout-Beispiel - Konfigurieren der Abmelde-URL, der Abmelde-Erfolgs-URL und Verwenden einer benutzerdefinierten Bean für erweiterte Abmelde-Szenarien.

Read more

2. Wann wird die Sitzung erstellt?

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

  • always - Eine Sitzung wird immer erstellt, wenn noch keine vorhanden ist

  • ifRequired - Eine Sitzung wird nur bei Bedarf erstellt (default).

  • never - Das Framework erstellt niemals selbst eine Sitzung, verwendet jedoch eine, wenn diese bereits vorhanden ist

  • stateless - Keine Sitzung wird von Spring Security erstellt oder verwendet

...

Java-Konfiguration:

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

Es ist sehr wichtig zu verstehen, dassthis configuration only controls what Spring Security does - nicht die gesamte Anwendung. Spring Security kann die Sitzung möglicherweise nicht erstellen, wenn wir dies nicht anweisen, aber unsere App kann dies!

StandardmäßigSpring Security will create a session when it needs one - dies ist „ifRequired“.

Füra more stateless application stellt die Option "never" 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 - "stateless" -guarantee that the application will not create any session at all.

Dies warintroduced in Spring 3.1 und überspringt effektiv Teile der Spring Security-Filterkette - hauptsächlich die sitzungsbezogenen Teile wieHttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter.

Diese strengeren Kontrollmechanismen haben die direkte Implikation, dasscookies are not used und damiteach and every request needs to be re-authenticated. Diese zustandslose Architektur eignet sich gut für REST-APIs und deren Zustandslosigkeitseinschränkungen. Sie funktionieren auch gut mit Authentifizierungsmechanismen wie der Standardauthentifizierung und der Digestauthentifizierung.

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 zuständig ist -SecurityContextPersistenceFilter. Der Kontext wird gemäß einer Strategie gespeichert - standardmäßigHttpSessionSecurityContextRepository -, die die HTTP-Sitzung als Speicher verwendet.

Für das strenge Attributcreate-session=”stateless” wird diese Strategie durch eine andere ersetzt -NullSecurityContextRepository - undno session will be created or used, um den Kontext beizubehalten.

4. Gleichzeitige Sitzungssteuerung

Wenn ein bereits authentifizierter Benutzer versucht,authenticate again zu erreichen, 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 zulassen, dass beide Sitzungen gleichzeitig existieren.

Der erste Schritt zum Aktivieren der gleichzeitigen Unterstützung vonsession-controlbesteht darin, denweb.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-Sitzungsregistrierungnotified when the session is destroyed lautet.

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


    
        
    

Oder über die Java-Konfiguration:

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

5. Session-Timeout

5.1. Behandeln des Sitzungszeitlimits

Wenn der Benutzer nach Ablauf der Sitzung eine Anforderung mit einemexpired session 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 ist, sondern vollständiginvalid, 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 Sitzungs-Timeout-Wert des eingebetteten Servers einfach mithilfe von Eigenschaften 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 gilt als ungültig.

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 von170s angeben, dies zu einem Timeout von 2 Minuten führt.

Schließlich ist es wichtig zu erwähnen, dass, obwohlSpring 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 Anzeigen von Sitzungsinformationen in der URL nimmt umsecurity riskzu (von Platz 7 im Jahr 2007 auf Platz 2 im Jahr 2013 in der OWASP-Top-10-Liste).

Starting with Spring 3.0, die URL-Umschreibungslogik, mit derjsessionid an die URL angehängt werden, kann jetzt deaktiviert werden, indemdisable-url-rewriting=”true” im Namespace<http> festgelegt wird.

Alternativ kann der Sitzungsverfolgungsmechanismus ab Servlet 3.0 auch inweb.xml: konfiguriert werden


     COOKIE

Und programmatisch:

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

Hiermit wird ausgewählt, wo dieJSESSIONID gespeichert werden sollen - im Cookie oder in einem URL-Parameter.

7. Sitzungsfixierungsschutz mit Spring Security

Das Framework bietet Schutz vor typischen Sitzungsfixierungsangriffen, indem konfiguriert wird, was mit einer vorhandenen Sitzung geschieht, wenn der Benutzer versucht, sich erneut 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 "none" eingestellt ist, wird die ursprüngliche Sitzung nicht ungültig

  • Wenn "newSession" festgelegt ist, wird eine saubere Sitzung erstellt, ohne dass eines der Attribute der alten Sitzung kopiert wird

Als Nächstes werden wir diskutieren, wie Sie unser Sitzungscookie sichern können.

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

  • httpOnly: Wenn true, kann das Browserskript nicht auf das Cookie zugreifen

  • secure: Wenn true, wird das Cookie nur über eine HTTPS-Verbindung gesendet

Wir können diese Flags für unser Sitzungscookie inweb.xml setzen:


    1
    
        true
        true
    

Diese Konfigurationsoption ist seit Java Servlet 3 verfügbar. Standardmäßig isthttp-only wahr undsecure ist falsch.

Schauen wir uns auch die entsprechende Java-Konfiguration an:

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

Schließlich können wir dies auch manuell erreichen, indem wirFilter verwenden:

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. Arbeiten mit der Sitzung

9.1. Bohnen mit Sitzungsumfang

Eine Bean kann mit dem Gültigkeitsbereich vonsessioneinfach mithilfe der Annotation @Scope für Beans definiert werden, die im Web-Kontext deklariert sind:

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

Oder mit XML:

Dann kann die Bohne einfach in eine andere Bohne injiziert werden:

@Autowired
private Foo theFoo;

Und Spring bindet die neue Bean an den Lebenszyklus der HTTP-Sitzung.

9.2. Injizieren der Raw-Sitzung in einen Controller

Die unformatierte HTTP-Sitzung kann auch direkt in dieController-Methode eingefügt werden:

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

9.3. Erhalten der Raw-Sitzung

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

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

10. Fazit

In diesem Artikel haben wir das Verwalten von Sitzungen mit Spring Security erörtert. Außerdem enthält die Federreferenz sehr guteFAQ on Session Management.

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