Skip to content

Commit

Permalink
Add support checking AnyRequestMatcher securityFilterChains
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Batischev authored and Max Batischev committed Jun 10, 2024
1 parent b4c8fdf commit f0b84d2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -63,6 +63,7 @@
import org.springframework.security.web.firewall.ObservationMarkingRequestRejectedHandler;
import org.springframework.security.web.firewall.RequestRejectedHandler;
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.RequestMatcherEntry;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -296,8 +297,20 @@ protected Filter performBuild() throws Exception {
requestMatcherPrivilegeEvaluatorsEntries
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
}
boolean anyRequestConfigured = false;
RequestMatcher matcher = null;
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
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);
requestMatcherPrivilegeEvaluatorsEntries
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -318,6 +318,14 @@ public void loadConfigWhenMultipleSecurityFilterChainAndIgnoringThenWebInvocatio
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) {
Authentication anotherUser = new TestingAuthenticationToken("anotherUser", "password", "ROLE_ANOTHER");
assertThat(privilegeEvaluator.isAllowed("/user", anotherUser)).isFalse();
Expand Down Expand Up @@ -819,4 +827,26 @@ public SecurityFilterChain permitAll(HttpSecurity http) throws Exception {

}

@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();
}

}

}

0 comments on commit f0b84d2

Please sign in to comment.