簡體   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