[英]Spring Boot, Spring Security, session-timeout issue with session scoped Bean, @PreDestroy
Fisrt, I need to say that I'm using session scoped bean. Fisrt,我需要说我正在使用会话范围的bean。 So before session is closed the preDestroy()
method is invoked 因此,在会话关闭之前,将调用preDestroy()
方法
@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. 当我使用Spring Security utils 注销时一切正常, preDestroy()
方法。
The main problems come when I use 我使用时会出现主要问题
server.session-timeout = 60
or = 1
in application.properties
application.properties
server.session-timeout = 60
或= 1
preDestroy()
is called approximately in 2.5 minutes after session has opened. 会话打开后大约在2.5分钟内调用preDestroy()
。 SecurityContextHolder.getContext().getAuthentication().getPrincipal();
更有趣的是SecurityContextHolder.getContext().getAuthentication().getPrincipal();
is null
. 是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
使用Provided Tomcat
时也存在问题
UPDATE: 更新:
The weird thing is that if I manually after 1 minute check the session existence the method
preDestroy()
is called immediately. 奇怪的是,如果我在1分钟后手动检查会话是否存在,则立即调用方法preDestroy()
。 ButSecurity Principal
is alreadynull
但Security Principal
已经是null
Thanks in Advance! 提前致谢!
When a session does timeout the SecurityContextHolder.getContext().getAuthentication().getPrincipal()
will always return null
. 当会话超时时, SecurityContextHolder.getContext().getAuthentication().getPrincipal()
将始终返回null
。 The SecurityContext
is only filled when a request comes in, one of the filters does that. SecurityContext
仅在请求进入时填充,其中一个过滤器执行此操作。 When a session times out the filters will of course not be invoked and as such the SecurityContext
not filled. 当会话超时时,过滤器当然不会被调用,因此SecurityContext
没有被填充。
Instead create a bean that implements ApplicationListener<HttpSessionDestroyedEvent>
. 而是创建一个实现ApplicationListener<HttpSessionDestroyedEvent>
的bean。 The HttpSessionDestroyedEvent
has a method getSecurityContexts
that returns the SecurityContext
s as originally in the HttpSession
. HttpSessionDestroyedEvent
有一个方法getSecurityContexts
,它返回最初在HttpSession
的SecurityContext
。
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: 正如M. Deinum所说:
There is a thread which check about every x seconds if sessions are invalid. 如果会话无效,则会有一个每隔x秒检查一次的线程。 So when your set your timeout to 1 minute it is 1 minute + a bit more before your sessions is actually cleared. 因此,当您将超时设置为1分钟时,它会在您的会话实际清除之前为1分钟+多一点。 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. 因此解释了preDestroy()
调用的延迟。
The next problem was how to get Security Principal
after SESSION-TIMEOUT 下一个问题是如何在SESSION-TIMEOUT之后获得Security Principal
NOTE that by implementing 注意通过实施
ApplicationListener<HttpSessionDestroyedEvent>
HttpSessionListener
Session scope bean
the 该
SecurityContextHolder.getContext().getAuthentication() == null
when appropriate destroy method is called 调用适当的destroy方法时,SecurityContextHolder.getContext().getAuthentication() == null
To get principal
visit relatedStackPost 要获得principal
访问relatedStackPost
After you'll do that implement HttpSessionListener
在你做完之后实现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");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.