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()
方法。
当我使用
时出现主要问题server.session-timeout = 60
中的 = 1
或application.properties
preDestroy()
大约在 2.5分钟中调用。SecurityContextHolder.getContext().getAuthentication().getPrincipal();
是null
。 我也试过了
@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return (ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) ->
configurableEmbeddedServletContainer.setSessionTimeout(1, TimeUnit.MINUTES);
}
我有同样的结果。
使用Provided Tomcat
时也存在问题
更新
奇怪的是,如果我在1分钟后手动检查会话 存在方法
preDestroy()
被立即调用。但Security Principal
已经null
提前致谢!
答案 0 :(得分:3)
当会话超时时,SecurityContextHolder.getContext().getAuthentication().getPrincipal()
将始终返回null
。 SecurityContext
仅在请求进入时填充,其中一个过滤器会执行此操作。当会话超时时,过滤器当然不会被调用,因此SecurityContext
未被填充。
而是创建一个实现ApplicationListener<HttpSessionDestroyedEvent>
的bean。 HttpSessionDestroyedEvent
有一个getSecurityContexts
方法可以返回SecurityContext
中最初的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.
}
}
}
答案 1 :(得分:1)
M。 Deinum 说:
如果会话有一个线程,每隔x秒检查一次 无效。因此,当您将超时设置为1分钟时,它是1分钟+ 在你的会话实际被清除之前多一点。当你检查 会话本身,无效会话已经被清理 它被强行检查。
因此解释了preDestroy()
调用的延迟。
下一个问题是如何在 SESSION-TIMEOUT 之后获得Security Principal
注意通过实施
ApplicationListener<HttpSessionDestroyedEvent>
HttpSessionListener
Session scope bean
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");
}
}