Search code examples
javaspringspring-securityspring-java-config

java.lang.IllegalStateException: getAttributeNames: Session already invalidated in Spring security HttpSessionDestroyedEvent


This exception happens when I try to handle SessionDestroyEvent:

public class SessionEndedListener implements ApplicationListener<SessionDestroyedEvent> {
    private final ContractorService contractorService;

    @Autowired
    public SessionEndedListener(ContractorService contractorService) {
        this.contractorService = contractorService;
    }

    @Override
    public void onApplicationEvent(SessionDestroyedEvent sessionDestroyedEvent) {
        sessionDestroyedEvent.getSecurityContexts()
    }
}

It occurs because in SessionDestroyedEvent Session already invalidate. But in HttpSessionEventPublisher Session is valid.

java.lang.IllegalStateException: getAttributeNames: Session already invalidated
    at org.apache.catalina.session.StandardSession.getAttributeNames(StandardSession.java:1199)
    at org.apache.catalina.session.StandardSessionFacade.getAttributeNames(StandardSessionFacade.java:120)
    at org.springframework.security.web.session.HttpSessionDestroyedEvent.getSecurityContexts(HttpSessionDestroyedEvent.java:51)
    at com.ordotrans.util.listener.SessionEndedListener.onApplicationEvent(SessionEndedListener.java:29)
    at com.ordotrans.util.listener.SessionEndedListener.onApplicationEvent(SessionEndedListener.java:18)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:159)
    at org.springframework.context.event.SimpleApplicationEventMulticaster$1.run(SimpleApplicationEventMulticaster.java:134)
    at java.lang.Thread.run(Thread.java:745)

Solution

  • I have found the solution, but it looks as a crutch.

    @WebListener
    public class SessionCounterListener implements HttpSessionListener {
    
        @Override
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            HttpSession session = httpSessionEvent.getSession();
            session.setMaxInactiveInterval(60*15);
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
    
            HttpSession session = httpSessionEvent.getSession();
            SessionDestroyedEvent sessionDestroyedEvent = new HttpSessionDestroyedEvent(session);
            ApplicationContext ctx =
                    WebApplicationContextUtils.
                            getWebApplicationContext(session.getServletContext());
            ContractorService contractorService = (ContractorService) ctx.getBean("contractorService");
            for (SecurityContext securityContext : sessionDestroyedEvent.getSecurityContexts()) {
                Authentication authentication = securityContext.getAuthentication();
                CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal();
    
            }
    
        }
    
    }