spring-security 如何使用spring SecurityWebFilterChain禁用/阻止除少数已知路径之外的所有非https请求

pod7payv  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(337)

我在Sping Boot Webflux应用程序中使用Spring安全性,主要为HTTPS端口上的流量提供服务。但是,作为一项操作要求,我需要在Spring Boot应用程序中支持几个非安全REST API路径,以便进行健康检查等,这些路径也需要在HTTP上公开。
那么,如何使用SecurityWebFilterChain bean强制所有对HTTPS的请求,除了已知路径之外?
这是我定义SecurityWebFilterChain bean的方式:

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {    
    @Bean
    SecurityWebFilterChain webFilterChain( ServerHttpSecurity http )
     throws Exception {
         return http 
            .authorizeExchange(exchanges -> exchanges
                    .anyExchange().permitAll()
                    .and()
                    .exceptionHandling()
                    .authenticationEntryPoint((exchange, exception) ->
                        Mono.error(exception))
                    )
            .csrf().disable()
            .headers().disable()
            .logout().disable()
            .build();
    }
}

这显然不会像预期的那样工作,因为它允许所有请求使用HTTPHTTPS方案,而我希望总是强制HTTPS,除了路径,例如/health
请建议我需要在上面的代码中进行哪些更改才能完成这项工作。

pinkon5k

pinkon5k1#

下面是我为解决这个问题而想到的方法。

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    private static final Set<String> UNSECURED = 
                 Set.of ( "/health", "/heartbeat" );

    @Bean
    SecurityWebFilterChain webFilterChain( final ServerHttpSecurity http ) {    
        return http
                .authorizeExchange(
                        exchanges -> exchanges
                        .matchers( this::blockUnsecured ).permitAll()
                        .and()
                        .exceptionHandling()
                        .authenticationEntryPoint(
                               (exchange, exception) -> Mono.error(exception))
                        )
                .csrf().disable()
                .headers().disable()
                .logout().disable()
                .httpBasic().disable()
                .build();
    }

    Mono<MatchResult> blockUnsecured( final ServerWebExchange exchange ) {    
        // Deny all requests except few known ones using "http" scheme
        URI uri = exchange.getRequest().getURI();

        boolean invalid = "http".equalsIgnoreCase( uri.getScheme() ) &&
                !UNSECURED.contains ( uri.getPath().toLowerCase() );    
        return invalid ? MatchResult.notMatch() : MatchResult.match();    
    }
}

不确定是否有更好的方法来做同样的事情。

jfewjypa

jfewjypa2#

通过复制HttpsRedirectWebFilter创建一个自定义过滤器,在该过滤器中,如果请求的url不是/health,您将对其进行修改,使其发送401而不是redirect

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {    
    @Bean
    SecurityWebFilterChain springWebFilterChain( ServerHttpSecurity http )
     throws Exception {
         return http.addFilterAt(your-custom-https-filter, 
                                 SecurityWebFiltersOrder.HTTPS_REDIRECT)
                    .
                  ......
    }

相关问题