Logout/Session timeout catching with spring security

后端 未结 3 1714
一向
一向 2020-11-28 21:16

I\'m using spring/spring-security 3.1 and want to take some action whenever the user logs out (or if the session is timed out). I managed to get the action done for logout b

相关标签:
3条回答
  • 2020-11-28 21:53

    You can use SimpleRedirectInvalidSessionStrategy to redirect to a URL when an invalid requested session is detected by the SessionManagementFilter.

    Sample applicationContext would be like this:

    <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"/>
    

    If you are using JSF, also refer to JSF 2, Spring Security 3.x and Richfaces 4 redirect to login page on session time out for ajax requests on how to handle Ajax requests as well.

    UPDATE: In such a case, you can extend the HttpSessionEventPublisher and listen for sessionDestroyed events like this:

    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);
       }
    
    }
    

    and then register this listener in your web.xml like this:

    <listener>
        <listener-class>com.examples.MyHttpSessionEventPublisher</listener-class>
     </listener>
    
    0 讨论(0)
  • 2020-11-28 21:59

    I've got a simpler solution. This works for both logout and session 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>
    
    0 讨论(0)
  • 2020-11-28 22:04

    Ok, I got a solution working, it's not as good as I'd like, but it get's me to the result.

    I create a bean from which I can get a hold of the ApplicationContext.

    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();
    }
    }
    

    I implement HttpSessionEventPublisher and on destroy, i get the UserDetails via sessionRegistry.getSessionInfo(sessionId)

    Now I have the spring beans which I need to do the cleanup of the session and the user for whom the session timed out for.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题