繁体   English   中英

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

[英]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

  1. 会话打开后大约在2.5分钟内调用preDestroy()
  2. 更有趣的是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 ,它返回最初在HttpSessionSecurityContext

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM