Вопрос по reflection, security, private, java – Как я могу получить доступ к закрытым методам и личным членам данных через рефлексию?

26

Я знаю, что мы можем получить доступ к приватному конструктору через@ Санджай Т. Шарма упомянул в своем ответе на мой вопрос:Делает & instancex Void & # x201D; всегда возвращать ложь?

Тем не мение,@duffymo сказал:

you can access private everything with reflection - methods, constructors, data members, everything.

How can I access the private methods and the private data members? Is it possible to access local variable via reflection? Is there a way to prevent anyone from accessing private constructors, methods, and data members?
@Thilo Это только члены данных, как насчет методов? Это так же? Eng.Fouad
Локальные переменные живут в стеке, а не в куче, так что это совершенно другая концепция. Но интересный вопрос в любом случае. Thilo
(Вы можете увидетьSecurityManager заставить вещи вести себя правильно. (И вы можете получить доступ к локальным полям через интерфейсы отладки / инструментария или внедрение байт-кода.)) Tom Hawtin - tackline
1. имеет дубликаты во всем, например:stackoverflow.com/questions/1555658/… Thilo

Ваш Ответ

6   ответов
9
  1. Using the method shown in the answer you linked to: setAccessible(true), which is a method of the superclass of Field, Constructor and Method.
  2. No.
  3. No, unless the code runs in a JVM you control, where you install a security manager. But if you give someone a jar file, and he uses the classes from this jar file, he'll be able to access everything.
Я не думаю, что это специфично для Java. Вы не можете защитить & quot; свою & quot; код от пользователя, который запускает его. Реализация DRM также борется с этим фактом. Удаленное выполнение (SaaS), вероятно, является единственным «решением». для этого. В любом случае, сокрытие информации в ООП - это не функция безопасности для сохранения секретов, а удобство для программиста, чтобы не видеть и не случайно связываться с внутренними компонентами реализации.
+1 так это один из минусов Java? Вы не можете защитить свои & lt; strike & gt; классы & lt; / strike & gt; код. Eng.Fouad
1

Пример как ниже:

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

class Test
{
    private int a = 5;   // Private data member

    private void call(int n) // Private method
    {
        System.out.println("in call()  n: " + n);
    }
}

public class Sample
{
    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException
    {
        Class c = Class.forName("Test");

        Object obj = c.newInstance();

        //---- Accessing a private method
        Method m=c.getDeclaredMethod("call",new Class[]{int.class});
        m.setAccessible(true);
        m.invoke(obj,7);

       //---- Accessing a private data member
       Field d = c.getDeclaredField("a");
       d.setAccessible(true);
       System.out.println(d.getInt(obj));
    }
}
3

To access a private field вам нужно будет позвонить Class.getDeclaredField(String name) или жеenter code here метод. Check this simple code:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}

PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue

To access a private method вам нужно будет вызвать метод Class.getDeclaredMethod (имя строки, Class [] parameterTypes) или Class.getDeclaredMethods ().

Check this simple code:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }

  private String getPrivateString(){
    return this.privateString;
  }
}
PrivateObject privateObject = new PrivateObject("The Private Value");

Method privateStringMethod = PrivateObject.class.
        getDeclaredMethod("getPrivateString", null);

privateStringMethod.setAccessible(true);

String returnValue = (String)
        privateStringMethod.invoke(privateObject, null);

System.out.println("returnValue = " + returnValue);

Читать подробнее на http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html

65

1) How can I access the private methods and the private data members?

Вы можете сделать это с небольшой помощьюsetAccessible(true) метод:

class Dummy{
    private void foo(){
        System.out.println("hello foo()");
    }
    private int i = 10;
}

class Test{
    public static void main(String[] args) throws Exception {
        Dummy d = new Dummy();

        /*---  [INVOKING PRIVATE METHOD]  ---*/
        Method m = Dummy.class.getDeclaredMethod("foo");
        //m.invoke(d); // Exception java.lang.IllegalAccessException
        m.setAccessible(true);//Abracadabra
        m.invoke(d); // Now it's OK

        /*---  [GETING VALUE FROM PRIVATE FIELD]  ---*/
        Field f = Dummy.class.getDeclaredField("i");
        //System.out.println(f.get(d)); // Not accessible now
        f.setAccessible(true); // Abracadabra
        System.out.println(f.get(d)); // Now it's OK

        /*---  [SETTING VALUE OF PRIVATE FIELD]  ---*/
        Field f2 = Dummy.class.getDeclaredField("i");
        //f2.set(d,20); // Not accessible now
        f2.setAccessible(true); // Abracadabra
        f2.set(d, 20); // Now it's OK
        System.out.println(f2.get(d));
    }
}

2) Is it possible to access a local variable via reflection?

Нет. Локальные переменные не могут быть доступны вне блока, в котором они были созданы (кто-то может сказать, что вы можете присвоить такую переменную полю, например,field = localVariable; и позже получить доступ к такому полю через отражение, но таким образом мы будем получать доступ кvalue, неvariable).

3) Is there any way to prevent anyone from accessing private constructors, methods, and data members?

Я думаю дляconstructors или жеmethods Вы могли бы использовать stacktrace, чтобы проверить, был ли он вызванReflection.
Для полей я не могу найти решение для предотвращения доступа к ним через отражение.

[WARNING: This is not approved by anyone. I just wrote it inspired by your question.]

class Dummy {
    private void safeMethod() {
        StackTraceElement[] st = new Exception().getStackTrace();
        // If a method was invoked by reflection, the stack trace would be similar
        // to something like this:
        /*
        java.lang.Exception
            at package1.b.Dummy.safeMethod(SomeClass.java:38)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        ->    at java.lang.reflect.Method.invoke(Method.java:601)
            at package1.b.Test.main(SomeClass.java:65)
        */
        //5th line marked by "->" is interesting one so I will try to use that info

        if (st.length > 5 &&
            st[4].getClassName().equals("java.lang.reflect.Method"))
            throw new RuntimeException("safeMethod() is accessible only by Dummy object");

        // Now normal code of method
        System.out.println("code of safe method");
    }

    // I will check if it is possible to normally use that method inside this class
    public void trySafeMethod(){
        safeMethod();
    }

    Dummy() {
        safeMethod();
    }
}

class Dummy1 extends Dummy {}

class Test {
    public static void main(String[] args) throws Exception {
        Dummy1 d1 = new Dummy1(); // safeMethod can be invoked inside a superclass constructor
        d1.trySafeMethod(); // safeMethod can be invoked inside other Dummy class methods
        System.out.println("-------------------");

        // Let's check if it is possible to invoke it via reflection
        Method m2 = Dummy.class.getDeclaredMethod("safeMethod");
        // m.invoke(d);//exception java.lang.IllegalAccessException
        m2.setAccessible(true);
        m2.invoke(d1);
    }
}

Output from Test main method:

code of safe method
code of safe method
-------------------
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at package1.b.Test.main(MyClass2.java:87)
Caused by: java.lang.RuntimeException: method safeMethod() is accessible only by Dummy object
    at package1.b.Dummy.safeMethod(MyClass2.java:54)
    ... 5 more
+1 интересный ответ. Eng.Fouad
1
 Area s=(Area)c.newInstance();  
 s.setRadius(10);
 System.out.println("Area: "+s.calculateArea(4));

 Method m[]=c.getDeclaredMethods(); 
  Constructor c1[]=c.getConstructors();  

 for(int i=0;i<m.length;i++)
     System.out.println(""+m[i]);

 for(int i=0;i<c1.length;i++)
     System.out.println(""+c1[i]);
0

Чтобы ответить на ваш третий вопрос:

  1. Is there a way to prevent anyone from accessing private constructors, methods, and data members?

Ответ:

Да, вы можете ограничить доступ (вы можете вызвать исключение, когда кто-то пытается получить доступ к вашему личному конструктору / методу / данным)

Обратитесь к приведенному ниже примеру:

******JavaSingleton Class******

package server;

public class JavaSingleton {

  private static final JavaSingleton INSTANCE = new JavaSingleton();

  private JavaSingleton() {
    if (INSTANCE != null) {
      throw new IllegalStateException("Inside JavaSingleton(): JavaSingleton " +
                                                        "instance already created.");
    }
    System.out.println("Inside JavaSingleton(): Singleton instance is being created.");
  }

  public static final JavaSingleton getInstance() {
    return INSTANCE;
  }
}


***Listing 2: JavaSingleton client***

import server.JavaSingleton;
import java.lang.reflect.*;

public class TestSingleton {

  public static void main(String[] args) throws ReflectiveOperationException {
    System.out.println("Inside main(): Getting the singleton instance using getInstance()...");
    JavaSingleton s = JavaSingleton.getInstance();

    System.out.println("Inside main(): Trying to use reflection to get another instance...");
    Class<JavaSingleton> clazz = JavaSingleton.class;
    Constructor<JavaSingleton> cons = clazz.getDeclaredConstructor();
    cons.setAccessible(true);
    JavaSingleton s2 = cons.newInstance();
  }
}

Output:

C:\singleton>java TestSingleton
Inside main(): Getting the singleton instance using getInstance()...
Inside JavaSingleton(): Singleton instance is being created.
Inside main(): Trying to use reflection to get another instance...
Exception in thread "main" java.lang.reflect.InvocationTargetException
  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
  at java.lang.reflect.Constructor.newInstance(Unknown Source)
  at TestSingleton.main(TestSingleton.java:13)
Caused by: java.lang.IllegalStateException: Inside JavaSingleton(): JavaSingleton instance already created.
  at server.JavaSingleton.<init>(JavaSingleton.java:7)
  ... 5 more

Этот пример был для одноэлементного класса (проверка в конструкторе), но вы все еще можете реализовать эту логику для частных методов, которые вы хотите запретить доступ из других классов.

В этом случае вы также объявите статический экземпляр и проверите его значение в приватном методе и выдадите ошибку в случае любого нежелательного значения.

Похожие вопросы