Доступ к эндпоинтам Java Spring Reactive WebFlux со списка разрешенных IP адресов/подсетей

e50304ee7089b2251486ac257b83347a

Очевидный пример состоит в использовании метода hasIpAddress (), однако данный метод в параметрах принимает всего лишь один IP адрес/подсеть:

@Configuration
@EnableWebFluxSecurity
@RequiredArgsConstructor
public class WebSecurity {
    @Bean
    public SecurityWebFilterChain filterNotificationEndpoint(final ServerHttpSecurity http) {
        return http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/endpoint1"))
                .authorizeExchange(exchange -> exchange.pathMatchers("/api/endpoint1")
                        .hasIpAddress("10.0.0.1/8"))
                .build();
    }
}

Рассмотрим случай, когда требуется ограничить работу эндпоинта по списку IP адресов/подсетей. Допустим, список задается в Spring конфиге application.yaml:

application:
  ip-whitelist:
    endpoint1IpWhiteList: 
      - 10.0.0.1/8
      - 11.0.0.1/8

Конфиг класс:

@ConfigurationProperties(prefix = "application.ip-whitelist")
@Component
@Getter
@Setter
@NoArgsConstructor
public class IpWhiteListProperties {
    private List endpoint1IpWhiteList;
}

В итоге, получаем следующую конфигурацию ограничения доступа по списку:

@Bean
public SecurityWebFilterChain filterNotificationEndpoint(final ServerHttpSecurity http) {
    var ipAddressListMatcher = new OrServerWebExchangeMatcher(
            ipWhiteListProperties.getEndpoint1IpWhiteList()
                    .map(IpAddressServerWebExchangeMatcher::new)
                    .collect(Collectors.toList()));
    return http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/endpoint1"))
            .authorizeExchange(exchange -> {
                exchange.pathMatchers("/api/endpoint1")
                        .access((authentication, context) -> Mono.just(context.getExchange())
                                .flatMap(ipAddressListMatcher::matches)
                                .map(matchResult -> new AuthorizationDecision(matchResult.isMatch())));
            })
            .build();
}

© Habrahabr.ru