此问题在此处已有答案:
Filter invoke twice when register as Spring bean(2个答案)
上个月关门了。
我尝试将自定义过滤器仅添加到特定的URL,但是过滤器会应用到每个请求,而不管URL和方法如何,有人知道使用Spring Security的最新版本修复此问题的正确方法吗,即不使用WebSecurityConfigurerAdapter,因为它将是deprecated。
这里有很多类似的问题,但它们要么对我不起作用,要么使用“旧”方法(如this和this以及许多其他方法),或者两者都有。
我暴露了许多端点,它们都遵循以下模式:/api/**
但是,我需要为特定端点提供一些身份验证:/api/some/url
和一个特定的方法(在本例中为GET
),如何正确地执行此操作?
注意:端点URL都在/api/*
下(它们应该称为嵌套吗?)
我的安全配置如下所示:
@EnableWebSecurity
public class SecurityConfig {
private MyFilter myFilter;
public SecurityConfig(MyFilter pif) {
myFilter = pif;
}
/**
* Handling AuthZ & AuthN for most APIs. No AuthZ & AuthN.
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain defaultSecurity(HttpSecurity http) throws Exception {
http.requestMatchers((requests) ->
requests.antMatchers("/"))
.authorizeHttpRequests((authorize) -> authorize.anyRequest()
.permitAll());
return http.build();
}
/**
* Handling AuthZ & AuthN for GET /api/some/url.
*/
@Bean
public SecurityFilterChain keyApiSecurity(HttpSecurity http) throws Exception {
http.requestMatchers((requests) -> requests
.antMatchers(HttpMethod.GET, "/api/some/url").and())
.addFilterBefore(myFilter,
BasicAuthenticationFilter.class)
.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll());
return http.build();
}
}
1条答案
按热度按时间jei2mxaa1#
当您在spring-boot中将一些
GenericFilter
实现公开为bean时,它会自动将其放入任何请求的公共过滤器链中,因为它不知道它是否是安全过滤器- * 它可能是日志记录过滤器或其他任何过滤器 *。因此,将执行此过滤器Bean而不考虑spring-security。
您的
defaultSecurity
过滤器链没有这个自定义过滤器,所以MyFilter
将在spring安全过滤器链之后执行。同时,
keyApiSecurity
过滤器链在BasicAuthenticationFilter
之前设置这个自定义过滤器,因此它将在那里执行,并且不会第二次执行,因为OncePerRequestFilter
s方法的基本doFilter()
实现检查请求是否已经被过滤器过滤。因此,如果您希望筛选器仅作为安全筛选器工作,则不应将其公开为bean,而应在安全筛选器链中设置它,如下所示:
你也应该考虑为一个“默认”的安全过滤器链设置最低的优先级,因为如果它是第一个被选中的-其他的安全过滤器链将被完全忽略。所以我认为一些特定的过滤器安全链应该有更高的优先级。
编辑:
如果因为依赖于
Filter
实现中的bean注入而无法使用new
操作符设置安全过滤器,则可以覆盖OncePerRequestFilter
的shouldNotFilter(HttpServletRequest request)
方法,例如:然后,它将只过滤匹配的请求,并将其放入安全过滤器链将设置其顺序。