[英]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
preDestroy()
。 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
,它返回最初在HttpSession
的SecurityContext
。
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.