Describe the bug
Long story short, we are using Spring Security on a Wildfly server, and when upgrading to Spring Security 6.5.9 (from Spring Security 5), we started getting errors along the lines of this one.
Caused by: java.lang.IllegalStateException: Couldn't find FilterChainProxy in [org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda/0x000001968bf54468@3d6a189b, FilterChainProxy[Filter Chains: null]]
at deployment.MY_WAR_FILE.war//org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.findFilterChainProxy(WebMvcSecurityConfiguration.java:320)
at deployment.MY_WAR_FILE.war//org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.<init>(WebMvcSecurityConfiguration.java:229)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at deployment.MY_WAR_FILE.war//org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:210)
... 43 more
Here is the method in Spring Security that is throwing the exception -- Lines 305-321 in WebMvcSecurityConfiguration.java.
|
/** |
|
* Find the FilterChainProxy in a List of Filter |
|
* @param filters |
|
* @return non-null FilterChainProxy |
|
* @throws IllegalStateException if the FilterChainProxy cannot be found |
|
*/ |
|
private static FilterChainProxy findFilterChainProxy(List<? extends Filter> filters) { |
|
for (Filter filter : filters) { |
|
if (filter instanceof FilterChainProxy fcp) { |
|
return fcp; |
|
} |
|
if (filter instanceof DebugFilter debugFilter) { |
|
return debugFilter.getFilterChainProxy(); |
|
} |
|
} |
|
throw new IllegalStateException("Couldn't find FilterChainProxy in " + filters); |
|
} |
Notice that it is using instanceof to check if the provided bean is a FilterChainProxy?
After attaching a debugger to our server, we found that it failed because our FilterChainProxy bean was a JDK Proxy, as opposed to a CGLIB Proxy!
JDK Dynamic Proxies can only be used with instanceof when comparing against an interface, not a class! And since FilterChainProxy is a class, then calling instanceof on our JDK Proxy fails every time!
Workaround
We managed to workaround this by simply turning our JDK Proxy beans into CGLIB Proxy Beans.
We did this by adding proxyTargetClass to our @EnableMethodSecurity annotation, like so.
OLD WAY -- @EnableMethodSecurity
NEW WAY -- @EnableMethodSecurity(proxyTargetClass = true)
Obviously, doing this has SWEEPING RAMIFICATIONS, as you have turned ALL OF YOUR BEANS to CGLIB style. That's not nothing lol. But for us, with a looming deadline and a not-too-complex codebase and security setup, it served us as a workaround.
To Reproduce
Special thanks to @udaykt for helping to create a reproducer!
git clone https://github.com/udaykt/spring-security-jdk-proxy-reproducer
cd spring-security-jdk-proxy-reproducer
mvn spring-boot:run
Expected behavior
Application should start successfully regardless of proxy strategy used for FilterChainProxy. At the very least, I would expect to be warned in the logs and/or the documentation for using JDK proxies.
Sample
https://github.com/udaykt/spring-security-jdk-proxy-reproducer
Describe the bug
Long story short, we are using Spring Security on a Wildfly server, and when upgrading to Spring Security 6.5.9 (from Spring Security 5), we started getting errors along the lines of this one.
Here is the method in Spring Security that is throwing the exception -- Lines 305-321 in
WebMvcSecurityConfiguration.java.spring-security/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java
Lines 305 to 321 in 0c54a55
Notice that it is using
instanceofto check if the provided bean is aFilterChainProxy?After attaching a debugger to our server, we found that it failed because our
FilterChainProxybean was a JDK Proxy, as opposed to a CGLIB Proxy!JDK Dynamic Proxies can only be used with
instanceofwhen comparing against aninterface, not aclass! And sinceFilterChainProxyis aclass, then callinginstanceofon our JDK Proxy fails every time!Workaround
We managed to workaround this by simply turning our JDK Proxy beans into CGLIB Proxy Beans.
We did this by adding
proxyTargetClassto our@EnableMethodSecurityannotation, like so.Obviously, doing this has SWEEPING RAMIFICATIONS, as you have turned ALL OF YOUR BEANS to CGLIB style. That's not nothing lol. But for us, with a looming deadline and a not-too-complex codebase and security setup, it served us as a workaround.
To Reproduce
Special thanks to @udaykt for helping to create a reproducer!
Expected behavior
Application should start successfully regardless of proxy strategy used for FilterChainProxy. At the very least, I would expect to be warned in the logs and/or the documentation for using JDK proxies.
Sample
https://github.com/udaykt/spring-security-jdk-proxy-reproducer