私人方法真的安全吗?

时间:2013-11-08 10:22:27

标签: java reflection private access-modifiers

在Java中,private访问修饰符被认为是安全的,因为它在类之外是不可见的。然后外界也不知道那种方法。

但我认为Java反射可以用来打破这个规则。请考虑以下案例:

public class ProtectedPrivacy{

  private String getInfo(){
     return "confidential"; 
  }

}  

现在从另一个班级我将获得信息:

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[]包含了上面需要做的所有事情。我的问题是,有没有办法避免使用Java反射这类事情?

我引用Java Documentation的一些观点来澄清我的问题。

  

选择访问级别的提示:

     

如果其他程序员使用您的课程,您需要确保错误   从滥用不可能发生。访问级别可以帮助您这样做。使用   对特定内容有意义的最严格的访问级别   会员。除非你有充分的理由不使用私人,否则请使用私人。

7 个答案:

答案 0 :(得分:95)

这取决于你所说的“安全”。如果你正在运行一个允许这种事情的安全管理器,那么是的,你可以用反射做各种讨厌的事情。但是在那种环境中,库可能只是被修改以使方法公开。

在这样的环境中,访问控制实际上是“建议性的” - 您实际上相信代码可以很好地发挥作用。如果信任您正在运行的代码,则应使用限制性更强的安全管理器。

答案 1 :(得分:40)

访问修饰符与安全性无关。实际上,您可以而且应该将访问修饰符视为安全性的反向 - 它不是为了保护您的数据或算法,而是为了保护人们免于了解您的数据和算法的要求。这就是默认修饰符是包的原因 - 如果它们正在处理它们可能已经需要知道的包。

随着对数据和代码方法的了解,知道何时以及如何使用它的响应能力。你没有在你的inIt方法上设置私人信息以防止别人发现它,你这样做是因为(a)他们不会知道你只在foo之后调用它并且只有当bar = 3.1415和(b)因为它对他们没有好处。

访问修饰符可以用一个简单的短语“TMI,伙计,我所以不需要知道”来总结。

答案 2 :(得分:7)

通过说'安全',您正在保护您或其他开发人员,他们使用您的API通过调用您的私有方法来损害对象。但是,如果您或他们真的需要调用此方法,他们可以使用Reflection。

答案 3 :(得分:6)

问题是你是谁试图保存。在我看来,你的代码的这样一个客户端是亏本的。

试图访问上述类private成员的任何代码(由您或其他人编写)实际上都在挖掘自己的坟墓。 private成员未参与公开 API,如有更改,恕不另行通知。如果客户端碰巧以上面给出的方式使用其中一个私有成员,那么如果它升级到私有成员被修改的API的较新版本,它将会中断。

答案 4 :(得分:5)

有了设施,就有了责任。你有不能做的事情,& 可以做的事情,但不应该做。

私人修饰符以最受限制的方式提供/使用。在课堂外不应看到的成员应被定义为私人。但是,正如我们所看到的那样,这可以用反思打破但这并不意味着你不应该使用私人 - 或者他们不安全。关于你应该明智地或以建设性的方式使用事物(如反思)。

答案 5 :(得分:5)

假设您信任API的客户端程序员,另一种看待他们使用这些特定功能的“安全”方式。

您公开提供的功能应该为您的代码提供清晰,记录良好,很少变化的界面。您的私有函数可以被视为实现细节,并且可能会随着时间的推移而发生变化,因此直接使用是不安全的。

如果客户程序员竭尽全力绕过这些抽象,那么他们就会宣称他们知道自己在做什么。更重要的是,他们知道它不受支持,可能会停止使用未来版本的代码。

答案 6 :(得分:5)

private不是为了安全,而是为了保持代码清洁并防止出错。它允许用户模块化代码(以及如何开发代码),而不必担心所有其他模块的细节

一旦您发布了代码,人们就可以弄清楚它是如何工作的。如果您最终希望代码在计算机上运行,​​则无法“隐藏”逻辑。即使编译成二进制文件也是一种混淆程度。

因此,您无法设置API来执行您不希望其他人能够调用的特殊事物。对于Web API,您可以将要控制的方法放在服务器端。