在 Spring Security 6 中使用两个或多个 SecurityFilterChains 无法正常工作,仅调用一个链

Rox*_*Rox 10 spring-security oauth-2.0 spring-boot spring-security-6

我很难SecurityFilterhain使用 Spring Security 6 让我的两个端点协同工作。对于我的一个端点路径 ( /v1/transactions/**),我希望用户使用 Oauth2 进行授权,而对于另一个端点路径 ( /v1/info) 则需要基本身份验证。只有其中一种配置可以按预期工作,具体取决于@Order()它们所拥有的配置。

通过以下两种SecurityFilterChain配置,我可以/v1/info使用基本身份验证发出请求,但不能使用 Oauth2 发出请求/v1/transaction/**,这只会给我 401 访问被拒绝。

basicAuthSecurityFilterChain如果我更改gets@Order(2)oauth2SecurityFilterChaingets的顺序,@Order(1)那么我可以调用/v1/transaction/**OAauth2,但不能调用/v1/infoBasic Auth,这会导致 401 Access Denied。

我不确定为什么会遇到这种行为,因为文档告诉我 SecurityFilterChain 的调用是根据路径决定的,并且基本 auth 和 oauth2 资源的路径是不同的(/v1/transaction/**vs /v1/info)。

@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
@EnableWebSecurity
@Configuration
public class BasicAuthSecurity {
    
    public AuthenticationManager authProviderManager() { //omitted code) }

    @Bean
    @Order(1)
    public SecurityFilterChain basicAuthSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authenticationManager(authProviderManager())
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(POST, "/v1/info", "/v1/info/{user}").hasRole("user")
                        .anyRequest().authenticated()
                )
                .httpBasic(withDefaults())
                .build();
    }
}

Run Code Online (Sandbox Code Playgroud)

对于 OAuth2 SecurityFilterChain 我正在使用这个:

@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
@EnableWebSecurity
@Configuration
public class Oauth2Security {

    @Bean
    @Order(2)
    public SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(POST, "/v1/transaction/**")
                        .hasAnyRole("poweruser", "admin")
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer()
                .jwt()
                .and().and().build();
    }
}
Run Code Online (Sandbox Code Playgroud)

ch4*_*4mp 13

securityMatcher您在 中的第一个过滤器链中丢失了@Order。就这么简单:/

    // Applies only to the specified security-matchers
    @Bean
    @Order(1)
    public SecurityFilterChain basicAuthSecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/v1/info/**");
        return http
                .authenticationManager(authProviderManager())
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(POST, "/v1/info", "/v1/info/{user}").hasRole("user")
                        .anyRequest().authenticated()
                )
                .httpBasic(withDefaults())
                .build();
    }
    
    // this one has lowest precedence (higher order) and no security matcher 
    // => behaves as default when higher precedence (lower order) ones security matchers did not match 
    @Bean
    @Order(2)
    public SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(POST, "/v1/transaction/**")
                        .hasAnyRole("poweruser", "admin")
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer()
                .jwt()
                .and().and().build();
    }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你!!它解决了它。奇怪的是,文档在第 9.4 章中没有提到“securityMatcher”,而是在第 16.3 章中首先提到。 (2认同)
  • 仅评估一个安全过滤器链,由安全匹配器决定哪一个。您的安全匹配器必须足够精确,以仅捕获要由其所属的过滤器链处理的请求。 (2认同)