Skip to content

Couldn't find FilterChainProxy when using JDK Proxy Beans, but works with CGLIB Proxy Beans #19207

@davidalayachew

Description

@davidalayachew

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions