Class TenantContextCleanupFilter
java.lang.Object
org.springframework.web.filter.GenericFilterBean
org.springframework.web.filter.OncePerRequestFilter
io.leandev.appfuse.security.tenant.TenantContextCleanupFilter
- All Implemented Interfaces:
jakarta.servlet.Filter, org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.DisposableBean, org.springframework.beans.factory.InitializingBean, org.springframework.context.EnvironmentAware, org.springframework.core.env.EnvironmentCapable, org.springframework.web.context.ServletContextAware
public class TenantContextCleanupFilter
extends org.springframework.web.filter.OncePerRequestFilter
租戶上下文清理 Filter
確保每個 HTTP 請求結束後清理 TenantContext 的 ThreadLocal,
防止在使用 Thread Pool 時發生跨請求的租戶 ID 洩漏。
為什麼需要這個 Filter?
- Servlet 容器(如 Tomcat)使用 Thread Pool 處理請求
- 如果某個請求設定了 ThreadLocal 但未清理,下一個請求可能會讀取到錯誤的租戶 ID
- 這是一個潛在的安全風險,可能導致跨租戶數據洩漏
配置方式:
方式 1:透過 @Bean 註冊(推薦)
@Configuration
public class TenantConfig {
@Bean
public FilterRegistrationBean<TenantContextCleanupFilter> tenantContextCleanupFilter() {
FilterRegistrationBean<TenantContextCleanupFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new TenantContextCleanupFilter());
registration.addUrlPatterns("/*");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
方式 2:透過 @Component 自動註冊
// 在應用層繼承並加上 @Component
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AppTenantContextCleanupFilter extends TenantContextCleanupFilter {
}
- See Also:
-
Field Summary
Fields inherited from class org.springframework.web.filter.OncePerRequestFilter
ALREADY_FILTERED_SUFFIXFields inherited from class org.springframework.web.filter.GenericFilterBean
logger -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voiddoFilterInternal(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, jakarta.servlet.FilterChain filterChain) boolean是否記錄 debug 日誌voidsetDebugEnabled(boolean debugEnabled) 設定是否記錄 debug 日誌Methods inherited from class org.springframework.web.filter.OncePerRequestFilter
doFilter, doFilterNestedErrorDispatch, getAlreadyFilteredAttributeName, isAsyncDispatch, isAsyncStarted, shouldNotFilter, shouldNotFilterAsyncDispatch, shouldNotFilterErrorDispatchMethods inherited from class org.springframework.web.filter.GenericFilterBean
addRequiredProperty, afterPropertiesSet, createEnvironment, destroy, getEnvironment, getFilterConfig, getFilterName, getServletContext, init, initBeanWrapper, initFilterBean, setBeanName, setEnvironment, setServletContext
-
Constructor Details
-
TenantContextCleanupFilter
public TenantContextCleanupFilter()預設建構子 -
TenantContextCleanupFilter
public TenantContextCleanupFilter(boolean debugEnabled) 建構子- Parameters:
debugEnabled- 是否記錄 debug 日誌
-
-
Method Details
-
doFilterInternal
protected void doFilterInternal(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, jakarta.servlet.FilterChain filterChain) throws jakarta.servlet.ServletException, IOException - Specified by:
doFilterInternalin classorg.springframework.web.filter.OncePerRequestFilter- Throws:
jakarta.servlet.ServletExceptionIOException
-
setDebugEnabled
public void setDebugEnabled(boolean debugEnabled) 設定是否記錄 debug 日誌- Parameters:
debugEnabled- 是否啟用
-
isDebugEnabled
public boolean isDebugEnabled()是否記錄 debug 日誌- Returns:
- 是否啟用
-