【问题标题】:Whitelist endpoint in spring-webflux security without context root path没有上下文根路径的spring-webflux安全中的白名单端点
【发布时间】:2021-07-04 19:21:35
【问题描述】:

我正在尝试将所有以 /health 结尾的自定义端点列入白名单,但在 WebFlux Security 中,我无法使用正则表达式来匹配所有端点。例如/app/health、/app/meta/health、/app/custom/meta/health、/api/app/custom/meta/health 等。我没有找到任何模式(或正则表达式)将这些列入白名单 -在构造 SecurityWebFilterChain 时用一个条目指向。 如果我尝试使用正则表达式,我也会收到警告

spring-security '**' patterns are not supported in the middle of patterns and will be rejected in the future. Consider using '*' instead for matching a single path segment.

下面是代码sn-p

String[] ALLOWED_PATTERNS = {".*/health"};
// String[] ALLOWED_PATTERNS = {"/*/health"};  // allows whitelist /app/health endpoint
// String[] ALLOWED_PATTERNS = {"/*/health", "/*/*/health"};  // need generic way to whitelist all

@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
    return http
        .authorizeExchange()
        .pathMatchers(ALLOWED_PATTERNS).permitAll()
        .anyExchange().authenticated()
         ...
        .build();
}

我可以通过提供 antMatchers 在 Spring Security 中实现相同的功能(不是响应式/Web Flux 安全性)

@Override
public void configure(WebSecurity web) {
   web.ignoring().antMatchers("/**/health");
}

注意:这不是弹簧执行器健康端点,而是自定义健康端点

【问题讨论】:

    标签: spring spring-boot spring-security spring-webflux whitelist


    【解决方案1】:

    您可以编写自己的匹配器。

    
    import com.google.common.cache.Cache;
    import com.google.common.cache.CacheBuilder;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import java.util.concurrent.ConcurrentMap;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    @Slf4j
    public class RegexRequestMatcher {
    
        private static final Cache<String, Pattern> CACHE = CacheBuilder.newBuilder().build();
        private static final ConcurrentMap<String, Pattern> PATTERNS = CACHE.asMap();
    
        public static Mono<ServerWebExchangeMatcher.MatchResult> matches(String regex, ServerWebExchange exchange) {
            return matches(regex, exchange.getRequest().getURI().getPath());
        }
    
        public static Mono<ServerWebExchangeMatcher.MatchResult> matches(String regex, String uri) {
            Pattern pattern = getPattern(regex);
            Matcher matcher = pattern.matcher(uri);
            boolean matches = matcher.matches();
            return Mono.just(matches)
                    .flatMap(m -> m ? ServerWebExchangeMatcher.MatchResult.match() : ServerWebExchangeMatcher.MatchResult.notMatch());
        }
    
        private static Pattern getPattern(String regex) {
            return PATTERNS.computeIfAbsent(regex, r -> Pattern.compile(r));
        }
    }
    
    

    然后,您可以使用自己的匹配器代替 pathMatchers。

    .matchers(exchange -> RegexRequestMatcher.matches(".*/health", exchange)).permitAll()
    

    【讨论】:

      猜你喜欢
      • 2018-08-18
      • 2012-11-19
      • 1970-01-01
      • 2020-04-13
      • 2019-02-25
      • 2021-08-10
      • 2020-11-18
      • 2020-10-09
      • 1970-01-01
      相关资源
      最近更新 更多