Spring Boot,Spring Security,会话范围Bean,会话超时问题,@ PreDestroy

时间:2015-09-14 16:53:26

标签: java spring-security spring-boot

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

中的

= 1application.properties

    会话开通后,
  1. preDestroy()大约在 2.5分钟中调用。
  2. 更有意思的是SecurityContextHolder.getContext().getAuthentication().getPrincipal();null
    但我已成功退出。
  3. 我也试过了

    @Bean
    public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
        return (ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) -> 
            configurableEmbeddedServletContainer.setSessionTimeout(1, TimeUnit.MINUTES);
        }
    

    我有同样的结果。
    使用Provided Tomcat时也存在问题

    更新

      

    奇怪的是,如果我在1分钟后手动检查会话   存在方法preDestroy()被立即调用。但   Security Principal已经null


    提前致谢!

2 个答案:

答案 0 :(得分:3)

当会话超时时,SecurityContextHolder.getContext().getAuthentication().getPrincipal()始终返回nullSecurityContext仅在请求进入时填充,其中一个过滤器会执行此操作。当会话超时时,过滤器当然不会被调用,因此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");

    }
}