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 实用程序注销一切正常时,将调用
preDestroy()
方法。当我使用时主要的问题来了
server.session-timeout = 60
中的= 1
或application.properties
会话打开后大约在 2.5分钟中调用
preDestroy()
。 SecurityContextHolder.getContext().getAuthentication().getPrincipal();
是null
。 但我已成功注销。 我也尝试过
@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return (ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) ->
configurableEmbeddedServletContainer.setSessionTimeout(1, TimeUnit.MINUTES);
}
我有相同的结果。
使用
Provided Tomcat
时也存在问题更新:
奇怪的是,如果我在一分钟后手动检查会话
存在方法
preDestroy()
被立即调用。但Security Principal
已经是null
提前致谢!
最佳答案
当会话超时时,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.
}
}
}