Add support checking AnyRequestMatcher securityFilterChains
Closes gh-15220
This commit is contained in:
parent
470cb46e38
commit
4c780bf8d4
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -63,6 +63,7 @@ import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandle
|
||||||
import org.springframework.security.web.firewall.ObservationMarkingRequestRejectedHandler;
|
import org.springframework.security.web.firewall.ObservationMarkingRequestRejectedHandler;
|
||||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||||
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -296,8 +297,20 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
||||||
requestMatcherPrivilegeEvaluatorsEntries
|
requestMatcherPrivilegeEvaluatorsEntries
|
||||||
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
|
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
|
||||||
}
|
}
|
||||||
|
boolean anyRequestConfigured = false;
|
||||||
|
RequestMatcher matcher = null;
|
||||||
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
|
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
|
||||||
SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
|
SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
|
||||||
|
Assert.isTrue(!anyRequestConfigured,
|
||||||
|
"A filter chain that matches any request has already been configured, which means that this filter chain for ["
|
||||||
|
+ matcher
|
||||||
|
+ "] will never get invoked. Please use `HttpSecurity#securityMatcher` to ensure that there is only one filter chain configured for 'any request' and that the 'any request' filter chain is published last.");
|
||||||
|
if (securityFilterChain instanceof DefaultSecurityFilterChain defaultSecurityFilterChain) {
|
||||||
|
matcher = defaultSecurityFilterChain.getRequestMatcher();
|
||||||
|
if (matcher instanceof AnyRequestMatcher) {
|
||||||
|
anyRequestConfigured = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
securityFilterChains.add(securityFilterChain);
|
securityFilterChains.add(securityFilterChain);
|
||||||
requestMatcherPrivilegeEvaluatorsEntries
|
requestMatcherPrivilegeEvaluatorsEntries
|
||||||
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
|
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -318,6 +318,14 @@ public class WebSecurityConfigurationTests {
|
||||||
assertThat(privilegeEvaluator.isAllowed("/ignoring1/child", null)).isTrue();
|
assertThat(privilegeEvaluator.isAllowed("/ignoring1/child", null)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void loadConfigWhenTwoSecurityFilterChainsPresentAndSecondWithAnyRequestThenException() {
|
||||||
|
assertThatExceptionOfType(BeanCreationException.class)
|
||||||
|
.isThrownBy(() -> this.spring.register(MultipleAnyRequestSecurityFilterChainConfig.class).autowire())
|
||||||
|
.havingRootCause()
|
||||||
|
.isExactlyInstanceOf(IllegalArgumentException.class);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertAnotherUserPermission(WebInvocationPrivilegeEvaluator privilegeEvaluator) {
|
private void assertAnotherUserPermission(WebInvocationPrivilegeEvaluator privilegeEvaluator) {
|
||||||
Authentication anotherUser = new TestingAuthenticationToken("anotherUser", "password", "ROLE_ANOTHER");
|
Authentication anotherUser = new TestingAuthenticationToken("anotherUser", "password", "ROLE_ANOTHER");
|
||||||
assertThat(privilegeEvaluator.isAllowed("/user", anotherUser)).isFalse();
|
assertThat(privilegeEvaluator.isAllowed("/user", anotherUser)).isFalse();
|
||||||
|
@ -819,4 +827,26 @@ public class WebSecurityConfigurationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
@Import(AuthenticationTestConfiguration.class)
|
||||||
|
static class MultipleAnyRequestSecurityFilterChainConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(0)
|
||||||
|
SecurityFilterChain api1(HttpSecurity http) throws Exception {
|
||||||
|
http.authorizeHttpRequests((auth) -> auth.anyRequest().authenticated());
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(1)
|
||||||
|
SecurityFilterChain api2(HttpSecurity http) throws Exception {
|
||||||
|
http.securityMatcher("/app/**").authorizeHttpRequests((auth) -> auth.anyRequest().authenticated());
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue