私人方法真的很安全吗?
在Java中, private
访问修饰符被认为是安全的,因为它在类之外是不可见的。 那么外界也不知道这个方法。
但是我认为Javareflection可以用来打破这个规则。 考虑以下情况:
public class ProtectedPrivacy{ private String getInfo(){ return "confidential"; } }
现在从另外一个class级我将获得信息:
public class BreakPrivacy{ public static void main(String[] args) throws Exception { ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy(); Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null); method.setAccessible(true); Object result = method.invoke(protectedPrivacy); System.out.println(result.toString()); } }
此时我只想到还有一些私人的方法,因为做了一些像上面这样的事情我们必须知道方法的名字。 但是如果包含其他人编写的私有方法的类我们没有这些可见性。
但是由于下面的代码,我的观点变得无效了。
Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();
现在这个method[]
包含了所有需要做的事情。 我的问题是,有没有办法避免使用Javareflection这种事情?
我引用了Java文档中的一些观点来澄清我的问题。
关于select访问级别的提示:
如果其他程序员使用你的类,你想确保不会发生错误使用的错误。 访问级别可以帮助您做到这一点。使用对特定成员有意义的限制性最强的访问级别。 除非你有充分的理由不要私下使用。
这取决于你的意思是“安全”。 如果你正在运行一个安全pipe理器,允许这样的事情,那么是的,你可以用reflection来做各种令人讨厌的事情。 但是,在那样的环境下,图书馆可能只是被修改来公开方法。
访问控制在这样的环境中是有效的“咨询” – 你确实相信代码可以很好地发挥作用。 如果您不信任正在运行的代码,则应该使用更严格的安全pipe理器。
访问修饰符与安全无关。 事实上,您可以也应该将访问修饰符视为安全性的反面 – 它不是保护您的数据或algorithm,而是保护人们不需要知道您的数据和algorithm。 这就是为什么默认修饰符是包 – 如果他们正在处理他们可能已经需要知道的包。
随着您的代码的数据和方法的知识,来了解何时以及如何使用它的响应。 你不要私下使用inIt方法来阻止某人发现它,你这样做是因为:(a)他们不会知道你只会在foo之后调用它,并且只有在bar = 3.1415和(b)因为这对他们不了解。
访问修饰符可以用一个简单的短语“TMI,老兄,我不需要知道这个”来概括。
通过说“安全”,您正在保护您或其他开发人员,通过调用您的私有方法来使用您的API不会损害对象。 但如果你或他们真的需要调用这个方法,他们可以用Reflection来完成。
问题是,你是从谁那里拯救出来的。 在我看来,这样的代码的客户端是在这里的一个损失。
任何试图访问上述类的private
成员的代码(由你或其他人编写)本质上都是挖掘自己的坟墓。 private
会员不参与公共 API,如有更改,恕不另行通知。 如果客户以上述方式使用这些私人成员之一,那么如果升级到私有成员被修改的API的更新版本,它将会中断。
随着设施,有责任。 有东西是你不能做的事情,你可以做的事情,但你不应该这样做。
私人修饰符以最受限制的方式被提供/使用。 在课堂以外不可见的成员应被定义为私人。 但是,我们可以看到,这可以通过reflection来打破。 但这并不意味着你不应该使用私人的,否则他们是不安全的。 这是关于你要审慎地或以build设性的方式(如反思)使用的东西。
假设你信任你的API的客户端程序员,另一种看待的方式是他们如何使用这些特定的function是“安全的”。
你公开的函数应该为你的代码提供一个清晰的,有详细logging的,很less变化的接口。 你的私有函数可以被认为是一个实现细节,可能会随着时间而改变,所以不直接使用安全。
如果一个客户程序员为了规避这些抽象而走出困境,他们会以某种方式宣称他们知道自己在做什么。 更重要的是,他们明白这是不受支持的,可能会停止使用未来版本的代码。
private
不是为了安全,而是为了保持代码清洁,防止错误。 它允许用户模块化代码(以及如何开发),而不必担心其他模块的所有细节
一旦你释放你的代码,人们可以弄清楚它是如何工作的。 如果您最终希望代码在计算机上运行,则无法“隐藏”逻辑。 即使编译为二进制也只是一个混淆的级别。
所以,你不可能设置你的API来做一些你不希望别人能够调用的特殊的东西。 在Web API的情况下,您可以将要控制的方法放在服务器端。