私人方法真的安全吗?

Ruc*_*era 92 java reflection private access-modifiers

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

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

public class ProtectedPrivacy{

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

}  
Run Code Online (Sandbox Code Playgroud)

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

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());
   }
} 
Run Code Online (Sandbox Code Playgroud)

此时我只是认为私有方法安全,因为做上面的事情我们必须知道方法名称.但是如果包含由其他人编写的私有方法的类我们没有那些可见性.

但是,由于下面的代码行,我的观点变得无效.

Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();
Run Code Online (Sandbox Code Playgroud)

现在这method[]包含了上面需要做的所有事情.我的问题是,有没有办法避免使用Java反射这类事情?

我引用Java文档中的一些观点来澄清我的问题.

选择访问级别的提示:

如果其他程序员使用您的类,您希望确保不会发生滥用错误.访问级别可以帮助您执行此操作.使用对特定成员有意义的最严格的访问级别.除非你有充分的理由不使用私人.

Jon*_*eet 95

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

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

  • @Gray:[SecurityManager]的一个实例(http://docs.oracle.com/javase/7/docs/api/java/lang/SecurityManager.html),它基本上会抛出相关`check*`调用的异常. (12认同)
  • 切,我知道,但是你能否详细说明一下这种意义上更严格的经理会是什么? (3认同)

jmo*_*eno 40

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

除了对数据和代码方法的了解外,还需要知道何时以及如何使用它.你不会在你的inIt方法中私有化以防止别人发现它,你这样做是因为(a)他们不会知道你只在foo之后调用它并且只有当bar = 3.1415和(b)因为它对他们没有好处.

访问修饰符可以用一个简单的短语"TMI,伙计,我所以不需要知道" 来概括.

  • 很好的答案,但我确实需要谷歌发现TMI意味着太多的信息.我想我需要在山谷里度过更多时间:-) (3认同)

Ars*_*yan 7

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


Nis*_*hth 6

问题是你想从谁那里拯救它.在我看来,你的代码的这样一个客户端是亏本的.

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


Raú*_*aúl 5

有了设施,就有了责任.有一件事情是,你不能做什么,和你的事情可以做,但你不应该做的.

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


rob*_*e_c 5

假设您信任API的客户端程序员,另一种看待他们使用这些特定功能的"安全"程度.

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

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


Man*_*rth 5

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

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

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