How to restrict developers to use reflection to access private methods and constructors in Java?
Using normal Java code we can't access private constructors or private methods outside of a class. But by using reflection we can access any private methods and constructors in a Java class.
So how can we give security to our Java code?
You can access the private methods of a class using java reflection package.
Despite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection. It is not even that difficult. This can be very handy during unit testing.
Yes, reflection is slow, and it creates fragile code when used in this way. If you want to avoid the if statement, you should use polymorphism.
Private fields are accessible on the class constructor from inside the class declaration itself. They are used for declaration of field names as well as for accessing a field's value.
Run your application using a SecurityManager
and a sufficiently restrictive security policy.
There's a short summary in the tutorial and extensive information in the security documentation.
Add checkPermission()
method in all of your private method/constructor.
checkPermission using sun.reflect.Reflection.getCallerClass(int n)
by assert callerClass=selfClass
.
The getCallerClass
returns the class of the method realFramesToSkip
frames up the stack (zero-based), ignoring frames associated with java.lang.reflect.Method.invoke()
and its implementation. The first frame is that associated with this method, so getCallerClass(0)
returns the Class object for sun.reflect.Reflection
.
public class PrivateConstructorClass {
private PrivateConstructorClass() {
checkPerMission();
//you own code go below
}
void checkPerMission() {
Class self = sun.reflect.Reflection.getCallerClass(1);
Class caller = sun.reflect.Reflection.getCallerClass(3);
if (self != caller) {
throw new java.lang.IllegalAccessError();
}
}
}
You can try to test reflect, it will fail:
public class TestPrivateMain {
Object newInstance() throws Exception {
final Class<?> c = Class.forName("package.TestPrivate");
final Constructor<?> constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
}
public static void main(String[] args) throws Exception {
Object t = new TestPrivateMain().newInstance();
}
}
You (as the developer of the code in question) cannot do that.
The end user, who runs the application, could install a SecurityManager that forbids reflection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With