spring - 禁用 WebFilter 的自动注册
问题描述
在 spring-boot 2.4 应用程序中,我有两个SecurityWebFilterChain
s. 对于其中一个,我想通过addFilterBefore()WebFilter
添加一些s 。
@Configuration
@EnableWebFluxSecurity
class WebSecurityConfig {
@Bean
fun filter1(service: Service): WebFilter = Filter1(service)
@Bean
fun filter2(component: Component): WebFilter = Filter2(component)
@Bean
@Order(1)
fun apiSecurityConfiguration(
http: ServerHttpSecurity,
filter1: WebFilter,
filter2: WebFilter
): SecurityWebFilterChain = http
.securityMatcher(pathMatchers("/path/**"))
.addFilterBefore(filter1, SecurityWebFiltersOrder.AUTHENTICATION)
.addFilterAt(filter2, SecurityWebFiltersOrder.AUTHENTICATION)
.build()
@Bean
@Order(2)
fun actuatorSecurityConfiguration(
http: ServerHttpSecurity,
reactiveAuthenticationManager: ReactiveAuthenticationManager
): SecurityWebFilterChain = http
.securityMatcher(pathMatchers("/manage/**"))
.authenticationManager(reactiveAuthenticationManager)
.httpBasic { }
.build()
}
但是,由于这些WebFilter
s 是作为 bean 创建的,它们会自动注册并应用于所有请求,似乎在安全链之外。
对于 servlet 过滤器,可以使用 a 禁用此注册FilterRegistrationBean
(请参阅spring-boot 文档)。
reactive 是否有类似WebFilter
的方法,或者我是否必须在这些过滤器中添加额外的 URL 过滤?
解决方案
要找到解决方案,我们首先必须更深入地研究弹簧的工作原理及其内部结构。
所有类型的 bean 都会WebFilter
自动添加到主 Web 处理过滤器链中。
请参阅有关该主题的spring boot 文档:
在应用程序上下文中找到的 WebFilter bean 将自动用于过滤每个交换。
即使您希望它们仅应用于特定的弹簧安全过滤器链,也会发生这种情况。
(恕我直言,重用Filter
orWebFilter
接口并且没有具有相同签名的特定于安全性的东西是spring-security的一个缺陷。)
在代码中,相关部分在spring-web的WebHttpHandlerBuilder中
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
// ...
List<WebFilter> webFilters = context
.getBeanProvider(WebFilter.class)
.orderedStream()
.collect(Collectors.toList());
builder.filters(filters -> filters.addAll(webFilters));
// ...
}
这又在 spring-boot 的HttpHandlerAutoConfiguration中调用以创建主 HttpHandler。
@Bean
public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) {
HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
// ...
return httpHandler;
}
为了防止将这些过滤器应用于所有交换,可以简单地不将它们创建为 bean 并手动创建它们,如上面的评论中所建议的那样。那么 BeanProvider 将不会找到它们并且不会将它们添加到 HttpHandler 中。但是,您离开 IoC 国家并失去过滤器的自动配置。当这些过滤器变得更复杂或当你有很多过滤器时,这并不理想。
因此,我的解决方案是为我的应用程序手动配置一个HttpHandler
,它不会将我的安全特定过滤器添加到全局过滤器链中。
为了完成这项工作,我首先为我的过滤器声明了一个标记接口。
interface NonGlobalFilter
class MySecurityFilter : WebFilter, NonGlobalFilter {
// ...
}
然后,在创建自定义 HttpHandler 的地方需要一个配置类。方便的是,WebHttpHandlerBuilder 有一个使用 Consumer操作其过滤器列表的方法。
这将阻止 spring-boot 从HttpHandlerAutoConfiguration使用它自己的 HttpHandler,因为它是用@ConditionalOnMissingBean(HttpHandler.class)
.
@Configuration
class WebHttpHandlerConfiguration(
private val applicationContext: ApplicationContext
) {
@Bean
fun httpHandler() = WebHttpHandlerBuilder
.applicationContext(applicationContext)
.filters {
it.removeIf {
webFilter -> webFilter is NonGlobalFilter
}
}
.build()
}
就是这样!与往常一样,spring 提供了许多开箱即用的有用默认值,但是当它妨碍您时,将有一种方法可以根据需要对其进行调整。
推荐阅读
- gnu - GNU LD:重叠部分 (NOLOAD) 不会产生错误
- css - 操作系统相关的浏览器开关
- r - 列表到 r 中的 data.frame
- shell - Unix:如何用另一个文件中的每个字符串替换一个模式
- c++ - 为什么在 Qt 中继承 QWidget 类时出现内存泄漏
- swift3 - 如何在 Swift 3 中创建类似于 Reddit 应用的顶级导航
- r - 如何在 R 中使用加权引导对数据进行重新采样?
- mern - NodeJS jwtStrategy 需要一个函数来从 MERN 中的请求错误中检索 jwt
- loops - 在链表制作的图中添加边
- r - 使用 R 在数据框中创建新列