[ https://issues.apache.org/jira/browse/WW-5534?focusedWorklogId=959780&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-959780 ]
ASF GitHub Bot logged work on WW-5534: -------------------------------------- Author: ASF GitHub Bot Created on: 03/Mar/25 11:09 Start Date: 03/Mar/25 11:09 Worklog Time Spent: 10m Work Description: kusalk commented on code in PR #1237: URL: https://github.com/apache/struts/pull/1237#discussion_r1977316681 ########## core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java: ########## @@ -510,9 +519,16 @@ protected StrutsParameter getParameterAnnotation(AnnotatedElement element) { return element.getAnnotation(StrutsParameter.class); } + protected Class<?> ultimateClass(Object action) { + if (ProxyUtil.isProxy(action)) { + return ProxyUtil.ultimateTargetClass(action); + } + return action.getClass(); + } + protected BeanInfo getBeanInfo(Object action) { try { - return Introspector.getBeanInfo(action.getClass()); + return ognlUtil.getBeanInfo(ultimateClass(action)); Review Comment: When I implemented this class, I forgot `OgnlUtil` already had a cached variant of this capability. We are now using that, and resolving any proxies to ensure annotation detection works as expected. ########## core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java: ########## @@ -212,16 +212,17 @@ protected boolean checkAllowlist(Object target, Member member) { return true; } + Class<?> targetClass = target != null ? target.getClass() : null; + if (!disallowProxyObjectAccess && ProxyUtil.isProxy(target)) { - // If `disallowProxyObjectAccess` is not set, allow resolving Hibernate entities to their underlying - // classes/members. This allows the allowlist capability to continue working and offer some level of + // If `disallowProxyObjectAccess` is not set, allow resolving Hibernate entities and Spring proxies to their + // underlying classes/members. This allows the allowlist capability to continue working and still offer // protection in applications where the developer has accepted the risk of allowing OGNL access to Hibernate - // entities. This is preferred to having to disable the allowlist capability entirely. - Object newTarget = ProxyUtil.getHibernateProxyTarget(target); - if (newTarget != target) { - logAllowlistHibernateEntity(target, newTarget); - target = newTarget; - member = ProxyUtil.resolveTargetMember(member, newTarget); + // entities and Spring proxies. This is preferred to having to disable the allowlist capability entirely. + Class<?> newTargetClass = ProxyUtil.ultimateTargetClass(target); Review Comment: We replaced `#getHibernateProxyTarget` with `#ultimateTargetClass` which can also resolve Spring proxies. This allows the OGNL allowlist to function in the presence of Spring proxies in applications where `struts.disallowProxyObjectAccess` has been reverted to `false`. ########## core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java: ########## Review Comment: I added comments for all the other tests in this class as I realised I didn't name them very well initially ########## core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java: ########## @@ -276,6 +384,27 @@ public void publicModelPojo() { assertThat(threadAllowlist.getAllowlist()).containsExactlyInAnyOrderElementsOf(getParentClasses(Object.class, Pojo.class)); } + /** + * Models of ModelDriven actions can be injected without any annotations on the Action, even when the Action is + * proxied. + */ + @Test + public void publicModelPojo_proxied() { + var proxyFactory = new ProxyFactory(new ModelAction()); Review Comment: We use the Spring proxy factory to create a CGLIB proxy like would occur when a transactional proxy is applied to a concrete Action class (like in the original bug report) Issue Time Tracking ------------------- Worklog Id: (was: 959780) Time Spent: 2h 10m (was: 2h) > Actions with Spring's @Transactional and ModelDriven > ---------------------------------------------------- > > Key: WW-5534 > URL: https://issues.apache.org/jira/browse/WW-5534 > Project: Struts 2 > Issue Type: Bug > Components: Core Interceptors, Plugin - Spring > Affects Versions: 7.0.0 > Reporter: Johannes Mayer > Priority: Minor > Fix For: 7.1.0 > > Time Spent: 2h 10m > Remaining Estimate: 0h > > Hi, > When using the ModelDriven interface, the getModel method has to be annotated > with {_}@StrutsParameter{_}. > When Spring decides to wrap an Action object with SpringCGLIB (e.g. when > annotating a method with {_}@Transactional){_}, one has to add the Package to > the allowList, so execute can be called. No harm done, just add this to the > {_}struts.xml{_}: > {code:java} > <constant name="struts.allowlist.packageNames" value="your.action.package"/> > {code} > The now emerging problem is, that > _org.apache.struts2.interceptor.parameter.ParametersInterceptor_ is not able > to map the request parameter to the model, because it is not able to find a > suitable _getModel_ method. The reason for this is, that the interceptor is > trying to find the annotation on the SpringCGLIB class, which does not work. > As a workaround, I can tell the ParameterInterceptor to not need a > _@StrutsParameter_ annotation, but imo that defeats the purpose of this > annotation. I am also warned not to make this configuration. I therefore > assume that this scenario is not desirable. > {code:java} > <constant name="struts.parameters.requireAnnotations" value="false" /> {code} > Spring's AopUtils gives the option the get to the real class: > _AopUtils.getTargetClass(springCGLIBObject);_ > I created a project to showcase this: > [https://github.com/sf-JMA/struts7-model-driven/|https://github.com/sf-JMA/struts7-model-driven/tree/main/src/main] > I added a test > [https://github.com/sf-JMA/struts7-model-driven/blob/main/src/test/java/com/steadforce/aek/struts7modeldriven/SpringAopVersusModelDrivenTest.java] > to show the AopUtils method. > -- This message was sent by Atlassian Jira (v8.20.10#820010)