mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-08 05:02:13 +00:00
Merge branch '6.3.x'
Closes gh-16063
This commit is contained in:
commit
5a95952c95
@ -34,6 +34,7 @@ import org.springframework.security.web.server.SecurityWebFilterChain;
|
|||||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||||
import org.springframework.security.web.server.WebFilterChainProxy.DefaultWebFilterChainDecorator;
|
import org.springframework.security.web.server.WebFilterChainProxy.DefaultWebFilterChainDecorator;
|
||||||
import org.springframework.security.web.server.WebFilterChainProxy.WebFilterChainDecorator;
|
import org.springframework.security.web.server.WebFilterChainProxy.WebFilterChainDecorator;
|
||||||
|
import org.springframework.security.web.server.firewall.ServerExchangeRejectedHandler;
|
||||||
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
|
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@ -81,11 +82,13 @@ class WebFluxSecurityConfiguration {
|
|||||||
|
|
||||||
@Bean(SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME)
|
@Bean(SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME)
|
||||||
@Order(WEB_FILTER_CHAIN_FILTER_ORDER)
|
@Order(WEB_FILTER_CHAIN_FILTER_ORDER)
|
||||||
WebFilterChainProxy springSecurityWebFilterChainFilter(ObjectProvider<ServerWebExchangeFirewall> firewall) {
|
WebFilterChainProxy springSecurityWebFilterChainFilter(ObjectProvider<ServerWebExchangeFirewall> firewall,
|
||||||
|
ObjectProvider<ServerExchangeRejectedHandler> rejectedHandler) {
|
||||||
WebFilterChainProxy proxy = new WebFilterChainProxy(getSecurityWebFilterChains());
|
WebFilterChainProxy proxy = new WebFilterChainProxy(getSecurityWebFilterChains());
|
||||||
WebFilterChainDecorator decorator = this.postProcessor.postProcess(new DefaultWebFilterChainDecorator());
|
WebFilterChainDecorator decorator = this.postProcessor.postProcess(new DefaultWebFilterChainDecorator());
|
||||||
proxy.setFilterChainDecorator(decorator);
|
proxy.setFilterChainDecorator(decorator);
|
||||||
firewall.ifUnique(proxy::setFirewall);
|
firewall.ifUnique(proxy::setFirewall);
|
||||||
|
rejectedHandler.ifUnique(proxy::setExchangeRejectedHandler);
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ import org.springframework.security.config.test.SpringTestContext;
|
|||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
|
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
|
||||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||||
|
import org.springframework.security.web.server.firewall.HttpStatusExchangeRejectedHandler;
|
||||||
|
import org.springframework.security.web.server.firewall.ServerExchangeRejectedHandler;
|
||||||
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
|
import org.springframework.security.web.server.firewall.ServerWebExchangeFirewall;
|
||||||
import org.springframework.web.server.handler.DefaultWebFilterChain;
|
import org.springframework.web.server.handler.DefaultWebFilterChain;
|
||||||
|
|
||||||
@ -70,6 +72,20 @@ public class WebFluxSecurityConfigurationTests {
|
|||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void loadConfigWhenCustomRejectedHandler() throws Exception {
|
||||||
|
this.spring
|
||||||
|
.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
|
||||||
|
WebFluxSecurityConfiguration.class, CustomServerExchangeRejectedHandlerConfig.class)
|
||||||
|
.autowire();
|
||||||
|
WebFilterChainProxy webFilterChainProxy = this.spring.getContext().getBean(WebFilterChainProxy.class);
|
||||||
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/;/").build());
|
||||||
|
DefaultWebFilterChain chain = emptyChain();
|
||||||
|
webFilterChainProxy.filter(exchange, chain).block();
|
||||||
|
assertThat(exchange.getResponse().getStatusCode())
|
||||||
|
.isEqualTo(CustomServerExchangeRejectedHandlerConfig.EXPECTED_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadConfigWhenFirewallBeanThenCustomized() throws Exception {
|
void loadConfigWhenFirewallBeanThenCustomized() throws Exception {
|
||||||
this.spring
|
this.spring
|
||||||
@ -107,6 +123,18 @@ public class WebFluxSecurityConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class CustomServerExchangeRejectedHandlerConfig {
|
||||||
|
|
||||||
|
static HttpStatus EXPECTED_STATUS = HttpStatus.I_AM_A_TEAPOT;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ServerExchangeRejectedHandler rejectedHandler() {
|
||||||
|
return new HttpStatusExchangeRejectedHandler(EXPECTED_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class SubclassConfig extends WebFluxSecurityConfiguration {
|
static class SubclassConfig extends WebFluxSecurityConfiguration {
|
||||||
|
|
||||||
|
@ -200,3 +200,35 @@ firewall.setAllowedHeaderValues {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
======
|
======
|
||||||
|
|
||||||
|
The `ServerExchangeRejectedHandler` interface is used to handle `ServerExchangeRejectedException` throw by Spring Security's `ServerWebExchangeFirewall`.
|
||||||
|
By default `HttpStatusExchangeRejectedHandler` is used to send an HTTP 400 response to clients when a request is rejected.
|
||||||
|
To customize the behavior, users can expose a `ServerExchangeRejectedHandler` Bean.
|
||||||
|
For example, the following will send an HTTP 404 when the request is rejected:
|
||||||
|
|
||||||
|
|
||||||
|
.Send 404 on Request Rejected
|
||||||
|
[tabs]
|
||||||
|
======
|
||||||
|
Java::
|
||||||
|
+
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
@Bean
|
||||||
|
ServerExchangeRejectedHandler rejectedHandler() {
|
||||||
|
return new HttpStatusExchangeRejectedHandler(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
Kotlin::
|
||||||
|
+
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@Bean
|
||||||
|
fun rejectedHandler(): ServerExchangeRejectedHandler {
|
||||||
|
return HttpStatusExchangeRejectedHandler(HttpStatus.NOT_FOUND)
|
||||||
|
}
|
||||||
|
----
|
||||||
|
======
|
||||||
|
|
||||||
|
Handling can be completely customized by creating a custom `ServerExchangeRejectedHandler` implementation.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user