[英]Spring Boot, Spring Security, session-timeout issue with session scoped Bean, @PreDestroy
Fisrt,我需要说我正在使用会话范围的bean。 因此,在会话关闭之前,将调用preDestroy()
方法
@Component
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "session")
public class MySessionBean {
@PreDestroy
public void preDestroy() {
//Do Smth with using Security principal
}
}
当我使用Spring Security utils 注销时一切正常, preDestroy()
方法。
我使用时会出现主要问题
application.properties
server.session-timeout = 60
或= 1
preDestroy()
。 SecurityContextHolder.getContext().getAuthentication().getPrincipal();
是null
。 我也试过了
@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return (ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) ->
configurableEmbeddedServletContainer.setSessionTimeout(1, TimeUnit.MINUTES);
}
我有相同的结果。
使用Provided Tomcat
时也存在问题
更新:
奇怪的是,如果我在1分钟后手动检查会话是否存在,则立即调用方法
preDestroy()
。 但Security Principal
已经是null
提前致谢!
当会话超时时, SecurityContextHolder.getContext().getAuthentication().getPrincipal()
将始终返回null
。 SecurityContext
仅在请求进入时填充,其中一个过滤器执行此操作。 当会话超时时,过滤器当然不会被调用,因此SecurityContext
没有被填充。
而是创建一个实现ApplicationListener<HttpSessionDestroyedEvent>
的bean。 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.
}
}
}
正如M. Deinum所说:
如果会话无效,则会有一个每隔x秒检查一次的线程。 因此,当您将超时设置为1分钟时,它会在您的会话实际清除之前为1分钟+多一点。 当您自己检查会话时,无效会话已经被清除,因为它被强制检查。
因此解释了preDestroy()
调用的延迟。
下一个问题是如何在SESSION-TIMEOUT之后获得Security Principal
注意通过实施
ApplicationListener<HttpSessionDestroyedEvent>
HttpSessionListener
Session scope bean
该
调用适当的destroy方法时,
SecurityContextHolder.getContext().getAuthentication() == null
要获得principal
访问relatedStackPost
在你做完之后实现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.