I want to contribute to the great answers by including some code. There are three beans that are super important in Spring Security. based on their types they are DelegatingFilterProxy
, FilterChainProxy
and SecurityFilterChain
.
DelegatingFilterProxy
delegates the job of filtering requests to a bean of type FilterChainProxy
which its name is springSecurityFilterChain
, and FilterChainProxy
is configured like this:
@Bean(
name = {"springSecurityFilterChain"}
)
public Filter springSecurityFilterChain() throws Exception {
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
if (!hasConfigurers) {
WebSecurityConfigurerAdapter adapter = (WebSecurityConfigurerAdapter)this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {
});
this.webSecurity.apply(adapter);
}
return (Filter)this.webSecurity.build();
}
springSecurityFilterChain
(or FilterChainProxy
) itself has a list of SecurityFilterChain
. SecurityFilterChain
itself has a list of Filter
instances that do the actual logic.
Every time we extend WebSecurityConfigurerAdapter
and override the configure(HttpSecurity httpSecurity)
method, we actually created a SecurityFilterChain
that is going to be used by springSecurityFilterChain
How springSecurityFilterChain
selects the appropriate SecurityFilterChain
from the list? based on the boolean matches(HttpServletRequest request)
method that is defined in the SecurityFilterChain
interface.
So HttpSecurity
is used to create a customized SecurityFilterChain
.
Now when WebSecurity
actually comes into play? WebSecurity
actually allow us to customize springSecurityFilterChain
(or FilterChainProxy
). take a look at how springSecurityFilterChain
is created.
It is the performBuild
method of WebSecurity
that is called for creating springSecurityFilterChain
bean.
@Override
protected Filter performBuild() throws Exception {
Assert.state(
!securityFilterChainBuilders.isEmpty(),
() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
+ "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
+ "More advanced users can invoke "
+ WebSecurity.class.getSimpleName()
+ ".addSecurityFilterChainBuilder directly");
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
chainSize);
for (RequestMatcher ignoredRequest : ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (debugEnabled) {
logger.warn("\n\n"
+ "********************************************************************\n"
+ "********** Security debugging is enabled. *************\n"
+ "********** This may include sensitive information. *************\n"
+ "********** Do not use in a production system! *************\n"
+ "********************************************************************\n\n");
result = new DebugFilter(filterChainProxy);
}
postBuildAction.run();
return result;
}
As you can see when Spring wants to registers SecurityFilterChain
into springSecurityFilterChain
bean for each web.ignoring()....
Spring is going to add a DefaultSecurityFilterChain
which is a custom implementation of SecurityFilterChain
into the beginning of the list.
When a request comes along springSecurityFilterChain
is going to check its list of SecurityFilterChain
in order to delegate the filtering job to that SecurityFilterChain
. springSecurityFilterChain
is going to call match
method of each SecurityFilterChain
. if the request URL starts with "/resources/**" in your case Spring
delegates the job of filtering request to an instance of DefaultSecurityFilterChain
in the beginning of the list and our custom SecurityFilterChain
s which is added by this line:
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
completely ignored.