2012-08-07 5 views
31

Ich benutze Frühling/Frühling-Sicherheit 3.1 und möchte etwas unternehmen, wenn der Benutzer abmeldet (oder wenn die Sitzung abgelaufen ist). Ich habe es geschafft, die Aktion zum Abmelden auszuführen, aber für das Session-Timeout kann ich nicht funktionieren.Abmelden/Sitzung Timeout mit Feder Sicherheit fangen

In web.xml habe ich nur den ContextLoaderListener angegeben (kann das das Problem sein?) Und natürlich die DelegatingFilterProxy.

Ich benutze die Auto-Konfiguration wie folgt.

Der Abmeldehandler wird aufgerufen, wenn der Benutzer auf Abmelden klickt, wodurch einige Aufrufe an eine Datenbank erfolgen.

Aber wie gehe ich mit dem Session-Timeout ???

Eine Möglichkeit, dies zu umgehen, wäre, den Benutzernamen in die Sitzung zu injizieren, wenn sich der Benutzer anmeldet und dann einen normalen httpsessionlistener verwendet und dasselbe bei Session-Timeout tut.

Gibt es einen ähnlichen Weg mit Feder Sicherheit, so dass, wenn Frühling entdeckt, dass die Sitzung zu Timeout ist, kann ich dort einhaken, Zugriff auf die Authentifizierung und holen Sie die UserDetails von dort und machen die Aufräumarbeiten.

Antwort

51

Ich habe eine einfachere Lösung. Dies funktioniert sowohl für das Abmelden als auch für das Sitzungs-Timeout.

@Component 
public class LogoutListener implements ApplicationListener<SessionDestroyedEvent> { 

    @Override 
    public void onApplicationEvent(SessionDestroyedEvent event) 
    { 
     List<SecurityContext> lstSecurityContext = event.getSecurityContexts(); 
     UserDetails ud; 
     for (SecurityContext securityContext : lstSecurityContext) 
     { 
      ud = (UserDetails) securityContext.getAuthentication().getPrincipal(); 
      // ... 
     } 
    } 

} 

web.xml:

<listener> 
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 
+1

Aus meiner Sicht ist dies die bessere Lösung. Ich empfehle dringend, dies zu verwenden, wie ich es tat. Danke John. Btw: Damit sind auch "normale" Logouts möglich! –

+0

Die hier erwähnte Sitzung bei der Verwendung von 'Spring Security' entspricht der HTTPSession oder handelt es sich um eine Spring Security-Sitzung? Die neue 'Spring Session' Komponente scheint eine Lösung zu bieten. Http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedevent – yathirigan

+5

@yathirigan Nicht sicher was du unter "Session of Spring Security" meinst. Spring Security verwendet eine HTTP-Sitzung, also ist es im Grunde dasselbe. – John29

3

Sie können SimpleRedirectInvalidSessionStrategy verwenden, um zu einer URL umzuleiten, wenn eine ungültige angeforderte Sitzung vom SessionManagementFilter erkannt wurde.

Probe application würde so aussehen:

<http> 
    <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" /> 
<http> 


<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter"> 
    <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" /> 
    <beans:property name="invalidSessionStrategy" ref="simpleRedirectInvalidSessionStrategy " /> 
</beans:bean> 

<beans:bean id="simpleRedirectInvalidSessionStrategy" class="org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy"> 
    <beans:constructor-arg name="invalidSessionUrl" value="/general/logins/sessionExpired.jsf" /> 
    <beans:property name="createNewSession" value="false" /> 
</beans:bean> 
<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/> 

Wenn Sie JSF verwenden, auch JSF 2, Spring Security 3.x and Richfaces 4 redirect to login page on session time out for ajax requests auf beziehen, wie auch Ajax-Anfragen zu behandeln.

UPDATE: In einem solchen Fall können Sie die HttpSessionEventPublisher erweitern und für sessionDestroyed Veranstaltungen wie diese hören:

package com.examples; 
import javax.servlet.http.HttpSessionEvent; 

import org.springframework.security.web.session.HttpSessionEventPublisher; 


public class MyHttpSessionEventPublisher extends HttpSessionEventPublisher { 

    @Override 
    public void sessionCreated(HttpSessionEvent event) { 
     super.sessionCreated(event); 
    } 

    @Override 
    public void sessionDestroyed(HttpSessionEvent event) { 
     //do something 
     super.sessionDestroyed(event); 
    } 

} 

und registrieren diese Zuhörer in Ihre web.xml wie folgt aus:

<listener> 
    <listener-class>com.examples.MyHttpSessionEventPublisher</listener-class> 
</listener> 
+0

Danke für den Vorschlag, aber ich denke nicht, dass dies das Problem lösen wird. Ich muss das Sitzungszeitlimit abfangen, ich kann nicht darauf warten, dass der Benutzer eine Anfrage macht (was er/sie manchmal nicht tun wird, z. B. Browser geschlossen). Ich muss einige Locks auflösen, die der Benutzer vielleicht genommen hat, die für jemand anderen sperren können. Nein, nicht mit JSF, nur Feder und Geschwindigkeit. – Perre

+0

Aktualisiert die Antwort! – Ravi

+0

Gibt es eine Möglichkeit, das Authentifizierungsobjekt zu erhalten? Ich habe es versucht, aber es über SecurityContextHolder.getContext() bekommen. GetAuthentication() gibt null zurück. Ich muss die Authentifizierung an die Sitzung direkt vor dem Timeout gebunden bekommen. Ich meine, das sieht für mich nach dem HttpSession expire Event aus. Wie kann ich das Authenticated UserDetails-Objekt aus diesem Ereignis entfernen? – Perre

6

Ok, ich habe eine funktionierende Lösung, es ist nicht so gut, wie ich möchte, aber es bringt mich zum Ergebnis.

Ich erstelle eine Bohne, von der ich den ApplicationContext erhalten kann.

public class AppCtxProvider implements ApplicationContextAware { 
private static WeakReference<ApplicationContext> APP_CTX; 

@Override 
public void setApplicationContext(ApplicationContext applicationContext) 
     throws BeansException { 
    APP_CTX = new WeakReference<ApplicationContext>(applicationContext); 
} 

public static ApplicationContext getAppCtx() { 
    return APP_CTX.get(); 
} 
} 

ich implementieren HttpSessionEventPublisher und zerstören, erhalte ich die Userdetails über sessionRegistry.getSessionInfo (sessionId)

Jetzt habe ich die Feder Bohnen, die ich brauche die Bereinigung der Sitzung zu tun und den Benutzer, für den die Sitzung endete für.

public class SessionTimeoutHandler extends HttpSessionEventPublisher { 
@Override 
public void sessionCreated(HttpSessionEvent event) { 
    super.sessionCreated(event); 
} 

@Override 
public void sessionDestroyed(HttpSessionEvent event) { 
    SessionRegistry sessionRegistry = getSessionRegistry(); 
    SessionInformation sessionInfo = (sessionRegistry != null ? sessionRegistry 
      .getSessionInformation(event.getSession().getId()) : null); 
    UserDetails ud = null; 
    if (sessionInfo != null) { 
     ud = (UserDetails) sessionInfo.getPrincipal(); 
    } 
    if (ud != null) { 
       // Do my stuff 
    } 
    super.sessionDestroyed(event); 
} 

private SessionRegistry getSessionRegistry() { 
    ApplicationContext appCtx = AppCtxProvider.getAppCtx(); 
    return appCtx.getBean("sessionRegistry", SessionRegistry.class); 
} 
Verwandte Themen