25

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?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Satya
  • 8,146
  • 9
  • 38
  • 43
  • This would be a nice option to have for signed jars. "Under no circumstances, allow reflection against classes in this jar file". But I think, there is no such feature. – Thilo Sep 27 '11 at 11:09

3 Answers3

21

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.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
6

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();
    }
} 
SiHa
  • 7,830
  • 13
  • 34
  • 43
swanliu
  • 781
  • 3
  • 8
1

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.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Of course he can. He installs the security manager during startign up of his application. – Angel O'Sphere Sep 27 '11 at 11:04
  • That is not an option unless he is the developer of the application. I was thinking more about the case where he "wants to restrict developers [presumably of the application] to use reflection" against the methods he'd like to keep private. – Thilo Sep 27 '11 at 11:08
  • What prevents him to have a static initializer in his classes that installs a security manager? And ofc throiws an exception that prevents class laoding, if he can't install it? – Angel O'Sphere Sep 27 '11 at 11:24