Spring Security's FilterChainProxy
2023 / 11 / 23 • Daniel Garnier-Moiroux
Earlier this month, I gave a 4-hour pre-conference workshop at JFall, focused on Spring Security. The goal was to demystify the architectural concepts that Spring Security builds upon, so attendees could start implementing their own use-cases easily, without banging their head on (mostly inadequate) StackOverflow answers.
You can find the workshop on GitHub if you’re interested.1
I got a question via e-mail a few days back, from Yağız:
I was trying to understand more about How
FilterChainProxy
is invoked inDelegatingFilterProxy
but it seems like it is not so easy to find how it is invoked. Is it possible for you to explain HowFilterChainProxy
invoked inDelegatingFilterProxy
.
Foreword
Before we dive into the explanation, two important warnings. First, this is an involved question, if you’ve never really heard about Filters and want to learn more, go watch one of my Spring Security talks first. I’ll wait for you.
You caught up? Good! Second caveat: those details are a framework-level concern, usually users don’t ever need to think about it! Sure, you might have your own very, very, VERY specific use-cases, but most of the time, that’s “below water” and you can Just Trust The Framework™.
Oh, and, please note: I’m not a super expert of how the core framework works internally, so some of my explantions might be slightly off (or maybe completely wrong?).
The explanation
The Spring Security reference doc is actually quite good at explaining this architecture, I recommend you check it out. It’s probably much better than my own explanation, but here we go:
First, DelegatingFilterProxy
is a Spring Framework class, for Web MVC. Basically, that’s a class for registering Filters as
Spring Beans. If we did not have this, we would have to register our filters using the painful
web.xml
file (examples here).
With the DelegatingFilterProxy
, “normal” Servlet Filters are wrapped into a Spring’s version of a
Servlet Filter, and so it benefits from Bean lifecycle management, for example. So think about it as
a way to register “general purpose Filters” into your servlet container, not just security filters –
in fact, the DelegatingFilterProxy
is always there, whether you have Spring Security or not. Some
example non-Spring-Security filters are listed in the Framework docs.
We have established that, in Spring, we always go through the DelegatingFilterProxy
to register
our servlet Filters.
The SecurityFilterChain,
a Spring Security concept, itself is NOT a Filter
, it’s just a “container” for security-related
Filters. As a reminder, security Filters are not registered as standalone filters, but all live in
the SecurityFilterChain
, and are a cohesive set of Filters that the Servlet container does not
know about, they just happen to be implemented as Filters. So we need a “bridge” between these
security Filters and the DelegatingFilterProxy
.
This is accomplished through the FilterChainProxy
– which a Spring Security, not Framework, class.
The FilterChainProxy
itself IS a Servlet Filter
, and thus is registered into the Spring
Framework ApplicationContext, and in the Servlet container, wrapped in a DelegatingFilterProxy
2.
It’s the Spring Security entrypoint when a request comes in.
The FilterChainProxy
contains multiple SecurityFilterChain
s, and decides which
SecurityFilterChain should be applied to an incoming request. In the FilterChainProxy’s “doFilter”
method, some security protections are applied, and the correct SecurityFilterChain is selected – all
of this in FilterChainProxy#doFilterInternal
With this SecurityFilterChain
selected, a VirtualFilterChain wrapping the SecurityFilterChain is created, and then #doFilter is invoked on that VirtualFilterChain
(which is only created for the request, unlike the SecurityFilterChain which is sort of a
“configuration” class). This is where Security Filters are called, and where you get to the more
“familiar” territory that I discuss in my talks.
Thanks for the great question, Yağız!
-
You can find the course material on GitHub, but it’s missing the explanations I give before each module, and the debriefs for particular pieces of code. To complement it, you could watch my Spring Security talk at Voxxed Zürich 2023, which is a good companion to the workshop. There are also longer versions of that talk, and versions in French - check out my talks page to find those. ↩
-
The registration happens in AbstractSecurityWebApplicationInitializer if you are really really curious about the internals, but honestly it’s very hard to follow. That’s because the
@Bean
that is wrapped in theDelegatingFilterProxy
is defined somewhere else, in WebSecurityConfiguration. ↩