Skip to content

Commit 7987c38

Browse files
committed
Improves two previous commit, by performance and bug safety
1 parent 56f31be commit 7987c38

File tree

4 files changed

+87
-21
lines changed

4 files changed

+87
-21
lines changed

core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java

+1-20
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
import com.opensymphony.xwork2.util.ProxyUtil;
1919
import ognl.DefaultMemberAccess;
20-
import org.apache.commons.lang3.reflect.FieldUtils;
21-
import org.apache.commons.lang3.reflect.MethodUtils;
2220
import org.apache.logging.log4j.LogManager;
2321
import org.apache.logging.log4j.Logger;
2422

@@ -87,7 +85,7 @@ public boolean isAccessible(Map context, Object target, Member member, String pr
8785
return false;
8886
}
8987

90-
if (isProxyAccess(target, member)) {
88+
if (ProxyUtil.isProxyMember(member, target)) {
9189
LOG.warn("Access to proxy [{}] is blocked!", member);
9290
return false;
9391
}
@@ -107,23 +105,6 @@ public boolean isAccessible(Map context, Object target, Member member, String pr
107105
return super.isAccessible(context, target, member, propertyName) && isAcceptableProperty(propertyName);
108106
}
109107

110-
protected boolean isProxyAccess(Object target, Member member) {
111-
if (!ProxyUtil.isProxy(target))
112-
return false;
113-
Class<?> clazz = ProxyUtil.ultimateTargetClass(target);
114-
if (member instanceof Method) {
115-
return null == MethodUtils.getMatchingMethod(clazz, member.getName(), ((Method) member).getParameterTypes());
116-
}
117-
if (member instanceof Field) {
118-
return null == FieldUtils.getField(clazz, member.getName(), true);
119-
}
120-
if (member instanceof Constructor) {
121-
return false;
122-
}
123-
124-
return true;
125-
}
126-
127108
protected boolean checkStaticMethodAccess(Member member) {
128109
int modifiers = member.getModifiers();
129110
if (Modifier.isStatic(modifiers)) {

core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java

+55-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
*/
1616
package com.opensymphony.xwork2.util;
1717

18+
import org.apache.commons.lang3.reflect.ConstructorUtils;
19+
import org.apache.commons.lang3.reflect.FieldUtils;
1820
import org.apache.commons.lang3.reflect.MethodUtils;
1921

20-
import java.lang.reflect.Proxy;
22+
import java.lang.reflect.*;
2123

2224
/**
2325
* <code>ProxyUtil</code>
@@ -60,6 +62,18 @@ public static boolean isProxy(Object object) {
6062
return isSpringAopProxy(object);
6163
}
6264

65+
/**
66+
* Check whether the given member is a proxy member of a proxy object.
67+
* @param member the member to check
68+
* @param object the object to check
69+
*/
70+
public static boolean isProxyMember(Member member, Object object) {
71+
if (!isProxy(object))
72+
return false;
73+
74+
return isSpringProxyMember(member);
75+
}
76+
6377
/**
6478
* Determine the ultimate target class of the given spring bean instance, traversing
6579
* not only a top-level spring proxy but any number of nested spring proxies as well &mdash;
@@ -95,6 +109,27 @@ private static boolean isSpringAopProxy(Object object) {
95109
|| isCglibProxyClass(clazz)));
96110
}
97111

112+
/**
113+
* Check whether the given member is a member of a spring proxy.
114+
* @param member the member to check
115+
*/
116+
private static boolean isSpringProxyMember(Member member) {
117+
try {
118+
Class<?> clazz = ClassLoaderUtil.loadClass(SPRING_ADVISED_CLASS_NAME, ProxyUtil.class);
119+
if (hasMember(clazz, member))
120+
return true;
121+
clazz = ClassLoaderUtil.loadClass(SPRING_TARGETCLASSAWARE_CLASS_NAME, ProxyUtil.class);
122+
if (hasMember(clazz, member))
123+
return true;
124+
clazz = ClassLoaderUtil.loadClass(SPRING_SPRINGPROXY_CLASS_NAME, ProxyUtil.class);
125+
if (hasMember(clazz, member))
126+
return true;
127+
} catch (ClassNotFoundException ignored) {
128+
}
129+
130+
return false;
131+
}
132+
98133
/**
99134
* Obtain the singleton target object behind the given spring proxy, if any.
100135
* @param candidate the (potential) spring proxy to check
@@ -136,4 +171,23 @@ private static boolean implementsInterface(Class<?> clazz, String ifaceClassName
136171
return false;
137172
}
138173
}
174+
175+
/**
176+
* Check whether the given class has a given member.
177+
* @param clazz the class to check
178+
* @param member the member to check
179+
*/
180+
private static boolean hasMember(Class<?> clazz, Member member) {
181+
if (member instanceof Method) {
182+
return null != MethodUtils.getMatchingMethod(clazz, member.getName(), ((Method) member).getParameterTypes());
183+
}
184+
if (member instanceof Field) {
185+
return null != FieldUtils.getField(clazz, member.getName(), true);
186+
}
187+
if (member instanceof Constructor) {
188+
return null != ConstructorUtils.getMatchingAccessibleConstructor(clazz, ((Constructor) member).getParameterTypes());
189+
}
190+
191+
return false;
192+
}
139193
}

core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java

+26
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,30 @@ public void testUltimateTargetClass() throws Exception {
8282
Class<?> testAspectUltimateTargetClass = ProxyUtil.ultimateTargetClass(testAspect);
8383
assertEquals(TestAspect.class, testAspectUltimateTargetClass);
8484
}
85+
86+
public void testIsProxyMember() throws Exception {
87+
Object simpleAction = appContext.getBean("simple-action");
88+
assertFalse(ProxyUtil.isProxyMember(
89+
simpleAction.getClass().getMethod("setName", String.class), simpleAction));
90+
91+
Object proxiedAction = appContext.getBean("proxied-action");
92+
assertTrue(ProxyUtil.isProxyMember(
93+
proxiedAction.getClass().getMethod("setExposeProxy", boolean.class), proxiedAction));
94+
95+
Object autoProxiedAction = appContext.getBean("auto-proxied-action");
96+
assertTrue(ProxyUtil.isProxyMember(
97+
autoProxiedAction.getClass().getMethod("getTargetClass"), autoProxiedAction));
98+
99+
Object pointcuttedTestBean = appContext.getBean("pointcutted-test-bean");
100+
assertTrue(ProxyUtil.isProxyMember(
101+
pointcuttedTestBean.getClass().getMethod("getTargetSource"), pointcuttedTestBean));
102+
103+
Object pointcuttedTestSubBean = appContext.getBean("pointcutted-test-sub-bean");
104+
assertFalse(ProxyUtil.isProxyMember(
105+
pointcuttedTestSubBean.getClass().getConstructor(), pointcuttedTestSubBean));
106+
107+
Object testAspect = appContext.getBean("test-aspect");
108+
assertFalse(ProxyUtil.isProxyMember(
109+
testAspect.getClass().getMethod("setExposeProxy", boolean.class), testAspect));
110+
}
85111
}

core/src/test/java/com/opensymphony/xwork2/spring/TestAspect.java

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public class TestAspect {
77
private int count;
88
private String name;
99
private int count2;
10+
private boolean exposeProxy;
1011

1112
String getIssueId() {
1213
return issueId;
@@ -43,4 +44,8 @@ public void setCount2(int count2) {
4344
log = log + "setCount2(" + count2 + ")-";
4445
this.count2 = count2;
4546
}
47+
48+
public void setExposeProxy(boolean exposeProxy) {
49+
this.exposeProxy = exposeProxy;
50+
}
4651
}

0 commit comments

Comments
 (0)