Fisrt, I need to say that I'm using session scoped bean. So before session is closed the preDestroy()
method is invoked
@Component
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "session")
public class MySessionBean {
@PreDestroy
public void preDestroy() {
//Do Smth with using Security principal
}
}
When I logout by using Spring Security utils everything goes fine, the preDestroy()
method is called.
The main problems come when I use
server.session-timeout = 60
or = 1
in application.properties
preDestroy()
is called approximately in 2.5 minutes after session has opened. SecurityContextHolder.getContext().getAuthentication().getPrincipal();
is null
. Also I've tried a
@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return (ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) ->
configurableEmbeddedServletContainer.setSessionTimeout(1, TimeUnit.MINUTES);
}
I have the same result.
Also the problem exists while using Provided Tomcat
UPDATE:
The weird thing is that if I manually after 1 minute check the session existence the method
preDestroy()
is called immediately. ButSecurity Principal
is alreadynull
Thanks in Advance!
When a session does timeout the SecurityContextHolder.getContext().getAuthentication().getPrincipal()
will always return null
. The SecurityContext
is only filled when a request comes in, one of the filters does that. When a session times out the filters will of course not be invoked and as such the SecurityContext
not filled.
Instead create a bean that implements ApplicationListener<HttpSessionDestroyedEvent>
. The HttpSessionDestroyedEvent
has a method getSecurityContexts
that returns the SecurityContext
s as originally in the HttpSession
.
public class YourListener implements ApplicationListener<HttpSessionDestroyedEvent> {
public void onApplicationEvent(HttpSessionDestroyedEvent evt) {
for (SecurityContext ctx : evt.getSecurityContexts() ) {
Authentication auth = ctx.getAuthentication();
Object principal = auth.getPrincipal();
// Do your thing with the principal.
}
}
}
As M. Deinum said:
There is a thread which check about every x seconds if sessions are invalid. So when your set your timeout to 1 minute it is 1 minute + a bit more before your sessions is actually cleared. When you check the session yourself, the invalid session is already cleaned as then it it is forcefully checked.
So delay of preDestroy()
invocation has been explained.
The next problem was how to get Security Principal
after SESSION-TIMEOUT
NOTE that by implementing
ApplicationListener<HttpSessionDestroyedEvent>
HttpSessionListener
Session scope bean
the
SecurityContextHolder.getContext().getAuthentication() == null
when appropriate destroy method is called
To get principal
visit relatedStackPost
After you'll do that implement HttpSessionListener
@Component
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
...
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession httpSession = httpSessionEvent.getSession();
SecurityContext securityContext = (SecurityContextImpl) httpSession.getAttribute("SPRING_SECURITY_CONTEXT");
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.