您不能真正使用反射扩展类,但可以封装它。
这当然是一个重大的安全风险,您应该认真考虑是否要允许这样做。
见:https ://web.archive.org/web/20120201052157/http://initbinder.com/articles/hack_any_java_class_using_reflection_attack.html
像这样的东西应该可以解决问题。
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.ClassNotFoundException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
import java.lang.NoSuchMethodException;
public class Tester {
private static String CLASS_NAME = "VictimClass";
private static Class victimClass = null;
private static Object victimClassObj = null;
public static void main(String[] args) {
victimClass = loadClass(victimClass, CLASS_NAME);
printClassStructure();
attack();
}
private static Class loadClass(Class clazz, String className) {
Thread thread = Thread.currentThread();
ClassLoader classLoader =
thread.getContextClassLoader();
try {
clazz = Class.forName(className, true, classLoader);
}
catch (ClassNotFoundException e) {
System.err.println("Error: could not find class: "
+ CLASS_NAME);
}
return clazz;
}
private static void printClassStructure() {
Constructor[] constructors =
victimClass.getDeclaredConstructors();
for (Constructor c : constructors) {
int modifier = c.getModifiers();
System.out.println("Declared constructor name: "
+ c.getName() + "ntis accessible: "
+ c.isAccessible() + "ntis private: "
+ Modifier.isPrivate(modifier) + "n");
}
Method[] methods = victimClass.getDeclaredMethods();
for (Method m : methods) {
int modifier = m.getModifiers();
System.out.println("Declared method name: " + m.getName()
+ "ntis accessible: "
+ m.isAccessible()
+ "ntis private: "
+ Modifier.isPrivate(modifier)
+ "ntis static: "
+ Modifier.isStatic(modifier) + "n");
}
Field[] fields = victimClass.getDeclaredFields();
for (Field f : fields) {
int modifier = f.getModifiers();
System.out.println("Declared field name: " + f.getName()
+ "ntis accessible: "
+ f.isAccessible()
+ "ntis private: "
+ Modifier.isPrivate(modifier)
+ "ntis static: "
+ Modifier.isStatic(modifier)
+ "ntis final: "
+ Modifier.isFinal(modifier) + "n");
}
}
private static void attack() {
Field[] fields = victimClass.getDeclaredFields();
Method[] methods = victimClass.getDeclaredMethods();
Constructor[] constructors = victimClass.getDeclaredConstructors();
//make constructor accessible
constructors[0].setAccessible(true);
System.err.println("Initiating reflection attack:");
try {
//create new object by invoking private constructor
victimClassObj = constructors[0].newInstance(new Object[] {});
//make static method accessible and get its value
//please note: when invoking static method,
//object represented by this Method is null
methods[2].setAccessible(true);
Object o = methods[2].invoke(null, new Object[] {});
System.out.println("Got user ID from private static accessor: "
+ o.toString());
//make method accessible and get its value
methods[0].setAccessible(true);
o = methods[0].invoke(victimClassObj, new Object[] {});
System.out.println("Got original password from private accessor: "
+ o.toString());
//make method accessible and set to it new value
methods[1].setAccessible(true);
System.out.println("Injecting new password using private mutator");
methods[1].invoke(victimClassObj, new Object[] {"injected_password"});
//get method’s its new value
o = methods[0].invoke(victimClassObj, new Object[] {});
System.out.println("Got injected password from private accessor: "
+ o.toString());
//make field accessible and get its value
fields[2].setAccessible(true);
o = fields[2].get(victimClassObj);
System.out.println("Got private field: " + o);
//make field accessible and set to it new value
System.out.println("Injecting value to a private field:");
fields[2].set(victimClassObj, "new_default_value");
//get field’s its new value
o = fields[2].get(victimClassObj);
System.out.println("Got updated private field: " + o);
//make field accessible and get its value
fields[1].setAccessible(true);
o = fields[1].get(victimClassObj);
System.out.println("Got private static field: " + o);
//make field accessible and set to it new value
System.out.println("Injecting value to a private static final field:");
fields[1].set(null, new Integer(2));
//get field’s its new value
o = fields[1].get(victimClassObj);
System.out.println("Got updated private static final field: " + o);
}
catch (InstantiationException e) {
System.err.println("Error: could not instantiate: " + e);
}
catch (IllegalAccessException e) {
System.err.println("Error: could not access: " + e);
}
catch (InvocationTargetException e) {
System.err.println("Error: could not invoke the target: " + e);
}
}
}