Skip to content

Commit e48d6b0

Browse files
committed
Support ServerWebExchangeFirewall @bean
Closes gh-15974
1 parent dd3c689 commit e48d6b0

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

Diff for: config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Arrays;
2020
import java.util.List;
2121

22+
import org.springframework.beans.factory.ObjectProvider;
2223
import org.springframework.beans.factory.annotation.Autowired;
2324
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
2425
import org.springframework.context.ApplicationContext;
@@ -30,6 +31,7 @@
3031
import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor;
3132
import org.springframework.security.web.server.SecurityWebFilterChain;
3233
import org.springframework.security.web.server.WebFilterChainProxy;
34+
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
3335
import org.springframework.util.ClassUtils;
3436
import org.springframework.util.ObjectUtils;
3537
import org.springframework.web.reactive.result.view.AbstractView;
@@ -65,8 +67,10 @@ void setSecurityWebFilterChains(List<SecurityWebFilterChain> securityWebFilterCh
6567

6668
@Bean(SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME)
6769
@Order(WEB_FILTER_CHAIN_FILTER_ORDER)
68-
WebFilterChainProxy springSecurityWebFilterChainFilter() {
69-
return new WebFilterChainProxy(getSecurityWebFilterChains());
70+
WebFilterChainProxy springSecurityWebFilterChainFilter(ObjectProvider<ServerWebExchangeFirewall> firewall) {
71+
WebFilterChainProxy webFilterChainProxy = new WebFilterChainProxy(getSecurityWebFilterChains());
72+
firewall.ifUnique(webFilterChainProxy::setFirewall);
73+
return webFilterChainProxy;
7074
}
7175

7276
@Bean(name = AbstractView.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)

Diff for: config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java

+46
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,24 @@
1616

1717
package org.springframework.security.config.annotation.web.reactive;
1818

19+
import java.util.Collections;
20+
21+
import org.jetbrains.annotations.NotNull;
1922
import org.junit.jupiter.api.Test;
2023
import org.junit.jupiter.api.extension.ExtendWith;
24+
import reactor.core.publisher.Mono;
2125

26+
import org.springframework.context.annotation.Bean;
2227
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.http.HttpStatus;
29+
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
30+
import org.springframework.mock.web.server.MockServerWebExchange;
2331
import org.springframework.security.config.test.SpringTestContext;
2432
import org.springframework.security.config.test.SpringTestContextExtension;
2533
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
2634
import org.springframework.security.web.server.WebFilterChainProxy;
35+
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
36+
import org.springframework.web.server.handler.DefaultWebFilterChain;
2737

2838
import static org.assertj.core.api.Assertions.assertThat;
2939

@@ -45,6 +55,28 @@ public void loadConfigWhenReactiveUserDetailsServiceConfiguredThenWebFilterChain
4555
assertThat(webFilterChainProxy).isNotNull();
4656
}
4757

58+
@Test
59+
void loadConfigWhenDefaultThenFirewalled() throws Exception {
60+
this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
61+
WebFluxSecurityConfiguration.class).autowire();
62+
WebFilterChainProxy webFilterChainProxy = this.spring.getContext().getBean(WebFilterChainProxy.class);
63+
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/;/").build());
64+
DefaultWebFilterChain chain = emptyChain();
65+
webFilterChainProxy.filter(exchange, chain).block();
66+
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
67+
}
68+
69+
@Test
70+
void loadConfigWhenFirewallBeanThenCustomized() throws Exception {
71+
this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
72+
WebFluxSecurityConfiguration.class, NoOpFirewallConfig.class).autowire();
73+
WebFilterChainProxy webFilterChainProxy = this.spring.getContext().getBean(WebFilterChainProxy.class);
74+
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/;/").build());
75+
DefaultWebFilterChain chain = emptyChain();
76+
webFilterChainProxy.filter(exchange, chain).block();
77+
assertThat(exchange.getResponse().getStatusCode()).isNotEqualTo(HttpStatus.BAD_REQUEST);
78+
}
79+
4880
@Test
4981
public void loadConfigWhenBeanProxyingEnabledAndSubclassThenWebFilterChainProxyExists() {
5082
this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
@@ -53,6 +85,20 @@ public void loadConfigWhenBeanProxyingEnabledAndSubclassThenWebFilterChainProxyE
5385
assertThat(webFilterChainProxy).isNotNull();
5486
}
5587

88+
private static @NotNull DefaultWebFilterChain emptyChain() {
89+
return new DefaultWebFilterChain((webExchange) -> Mono.empty(), Collections.emptyList());
90+
}
91+
92+
@Configuration
93+
static class NoOpFirewallConfig {
94+
95+
@Bean
96+
ServerWebExchangeFirewall noOpFirewall() {
97+
return ServerWebExchangeFirewall.INSECURE_NOOP;
98+
}
99+
100+
}
101+
56102
@Configuration
57103
static class SubclassConfig extends WebFluxSecurityConfiguration {
58104

0 commit comments

Comments
 (0)