Describe the bug
ContextAwareServerHttpSecurity visibility does not allow it to be proxied via an Aspect call. Any attempt to do so causes the app to fail during startup with the following stack trace.
Caused by: java.lang.IllegalArgumentException: No visible constructors in class org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfiguration$ContextAwareServerHttpSecurity
at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:57) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:362) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:103) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52) ~[spring-core-6.0.8.jar:6.0.8]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:126) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:313) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:62) ~[spring-aop-6.0.8.jar:6.0.8]
at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:213) ~[spring-aop-6.0.8.jar:6.0.8]
... 36 common frames omitted
To Reproduce Spring Boot: 3.0.6 Spring Dependency Management: 1.1.0 Kotlin: 1.7.22 Java Version: 17
You can run the sample app linked below or simply try to run the aspect below for an app that is referencing the ServerHttpSecurity class.
@Aspect
@Component
class AspectTest {
@Before(
"execution(public * org.springframework.security.config.web.server.ServerHttpSecurity.authorizeExchange()) " +
"&& target(serverHttpSecurity)"
)
fun updateServerHttpSecurity(serverHttpSecurity: ServerHttpSecurity) {
println("We are here $serverHttpSecurity")
}
}
Expected behavior
I expect to be able to run the aspect on the ServerHttpSecurity class.
Sample https://github.com/btkelly/spring-security-aspect-bug
Comment From: marcusdacoregio
Hi @btkelly,
I'd like to know more about what you are trying to achieve here. As far as I can tell you want to customize the ServerHttpSecurity bean before injecting it into the methods.
Have you considered creating the bean and applying your configuration without relying on something more complex like Aspect? It would look something like this:
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Primary
ServerHttpSecurity myServerHttpSecurity() {
ContextAwareServerHttpSecurity http = new ContextAwareServerHttpSecurity();
http
// ... your configuration
return http;
}
private static class ContextAwareServerHttpSecurity extends ServerHttpSecurity implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
super.setApplicationContext(applicationContext);
}
}
Comment From: btkelly
@marcusdacoregio We're basically building out a set of libraries for projects at our company to leverage and the aspect was a way to apply logic to the security configuration irrelevant of how a consumer had created it. We tried your solution and I think it should fit our use cases enough and we'll just make sure teams are not creating the ServerHttpSecurity instance directly. Thanks for the response and a viable solution! Closing this issue now 👍