繁体   English   中英

Java阻止在类外调用私有或受保护的方法

[英]Java prevent calling private or protected methods outside of class

让我们假设我创建了一个名为Foo的Java库,我在该库中有一个名为Bar 让我们进一步假设在Bar类中我有一个名为fooBar的私有方法。

public class Bar {
    //...
    private Object fooBar() {
        //Do something
    }
    //...
}

可以使用类中编写的代码毫无困难地运行此方法,如下所示:

public static Object runMethod(Object object, String methodName) {
    Method method = object.getClass().getDeclaredMethod(methodName);
    method.setAccessible(true);
    return method.invoke(object);
}

但是,让我们假设我们打算劝阻fooBar这个习惯。 我们怎么能这样做呢? 我们应该从某处获取堆栈跟踪并检查它的调用位置吗? 或者我们应该做别的事吗?

你需要一个安全经理......

https://docs.oracle.com/javase/tutorial/essential/environment/security.html

安全管理器是定义应用程序安全策略的对象。 此策略指定不安全或敏感的操作。 安全策略不允许的任何操作都会导致抛出SecurityException。 应用程序还可以查询其安全管理器以发现允许的操作。

它支持禁止setAccessible()使私有和受保护的方法通过反射可调用。

我想如果你想成为极端,你可以得到这样的堆栈跟踪:

public class Bar {
    //...
    private Object fooBar() {
        try {
            throw new CheckIfCalledFromMethodException(); 
        } catch(CheckIfCalledFromMethodException e) {
            //here you have access to stack trace in your exception
        }

        //Do something
    }
    //...
}

我整理了一个简单的场景,它检查调用该类的second实例是否是同一个对象或其他东西。

public class StackTraceTest {
    private void execute() {
        try {
            throw new Exception();
        } catch (Exception e) {
            /*for(int i = 0; i < e.getStackTrace().length; i++) {
                StackTraceElement stackTraceElement = e.getStackTrace()[i];
                System.out.println(stackTraceElement.getFileName());
            }
            System.out.println("");
            e.printStackTrace();*/
            if(!e.getStackTrace()[1].getFileName().equals(StackTraceTest.class.getSimpleName() + ".java")) {
                throw new IllegalAccessError("Illegal Access.");
            }
        }
    }

    public void executeExternal() {
        this.execute();
    }
}

public class AccsessorTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StackTraceTest stackTraceTest = new StackTraceTest();
        stackTraceTest.executeExternal();
        System.out.println("Accessed from within other method in class.");
        System.out.println("");
        Class<?> clazz = StackTraceTest.class;
        Method method = clazz.getDeclaredMethod("execute");
        method.setAccessible(true);
        System.out.println("Accessing through reflection...");
        method.invoke(stackTraceTest);
    }
}

然后我明白了

Accessed from within other method in class.

Reflection test start.
Accessing through reflection...
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at stacktracetest.another.AccsessorTest.main(AccsessorTest.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.IllegalAccessError: Illegal Access.
    at stacktracetest.StackTraceTest.execute(StackTraceTest.java:18)
    ... 10 more

所以我想可以用堆栈跟踪元素魔法来检查,但是你应该检查一下它是否真的有效,这是非常粗糙的,我只是在一秒钟之前把它放在一起。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM