Skip to content

Commit 95e3f37

Browse files
committed
Improve Error Message for Conflicting Filter Chains
Closes gh-15874
1 parent a367569 commit 95e3f37

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,16 +302,16 @@ protected Filter performBuild() throws Exception {
302302
requestMatcherPrivilegeEvaluatorsEntries
303303
.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
304304
}
305-
boolean anyRequestConfigured = false;
305+
DefaultSecurityFilterChain anyRequestConfigured = null;
306306
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
307307
SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
308-
Assert.isTrue(!anyRequestConfigured,
309-
"A filter chain that matches any request has already been configured, which means that this filter chain ["
310-
+ securityFilterChain
311-
+ "] 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.");
308+
Assert.isTrue(anyRequestConfigured == null, "A filter chain that matches any request ["
309+
+ anyRequestConfigured + "] has already been configured, which means that this filter chain ["
310+
+ securityFilterChain
311+
+ "] 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.");
312312
if (securityFilterChain instanceof DefaultSecurityFilterChain defaultSecurityFilterChain) {
313313
if (defaultSecurityFilterChain.getRequestMatcher() instanceof AnyRequestMatcher) {
314-
anyRequestConfigured = true;
314+
anyRequestConfigured = defaultSecurityFilterChain;
315315
}
316316
}
317317
securityFilterChains.add(securityFilterChain);

web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
import jakarta.servlet.http.HttpServletRequest;
2525
import org.apache.commons.logging.Log;
2626
import org.apache.commons.logging.LogFactory;
27+
import reactor.util.annotation.NonNull;
2728

29+
import org.springframework.beans.factory.BeanNameAware;
2830
import org.springframework.core.log.LogMessage;
2931
import org.springframework.security.web.util.matcher.RequestMatcher;
3032
import org.springframework.util.StringUtils;
@@ -36,14 +38,16 @@
3638
* @author Jinwoo Bae
3739
* @since 3.1
3840
*/
39-
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
41+
public final class DefaultSecurityFilterChain implements SecurityFilterChain, BeanNameAware {
4042

4143
private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
4244

4345
private final RequestMatcher requestMatcher;
4446

4547
private final List<Filter> filters;
4648

49+
private String beanName;
50+
4751
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
4852
this(requestMatcher, Arrays.asList(filters));
4953
}
@@ -80,8 +84,24 @@ public boolean matches(HttpServletRequest request) {
8084

8185
@Override
8286
public String toString() {
83-
return this.getClass().getSimpleName() + " [RequestMatcher=" + this.requestMatcher + ", Filters=" + this.filters
84-
+ "]";
87+
List<String> filterNames = new ArrayList<>();
88+
for (Filter filter : this.filters) {
89+
String name = filter.getClass().getSimpleName();
90+
if (name.endsWith("Filter")) {
91+
name = name.substring(0, name.length() - "Filter".length());
92+
}
93+
filterNames.add(name);
94+
}
95+
String declaration = this.getClass().getSimpleName();
96+
if (this.beanName != null) {
97+
declaration += " defined as '" + this.beanName + "'";
98+
}
99+
return declaration + " matching [" + this.requestMatcher + "] and having filters " + filterNames;
100+
}
101+
102+
@Override
103+
public void setBeanName(@NonNull String name) {
104+
this.beanName = name;
85105
}
86106

87107
}

0 commit comments

Comments
 (0)