私有成员在Java中真的更“安全”吗?

学习Java我有时被教导使用private访问修饰符,以免将“敏感信息”暴露给其​​他类,好像这可能会打开一个合法的安全漏洞。 但是我从来没有遇到过限制成员可见性不仅仅是以面向对象的方式建模程序的便利的情况。

Java类中的private字段和函数实际上是否比其他类更“安全”?


编辑 – 汇编最佳答案。

为什么private并不意味着“安全”:

  • 反编译器允许静态查看字节码
  • reflection库允许运行时访问私有成员

private有什么好处:

  • 由于强制方法级访问而导致的代码可维护性
  • 隐藏实现细节的代码模块化

我从来没有听说过 – 在任何严肃的意义上 – 作为一个安全问题。 我的意思是,反编译工作。 您可以使用它们来弄清楚字节码内部发生了什么。

拥有private成员是一个可维护性问题。 如果我只给你方法级访问我的内部,那么我唯一的责任是确保我的API方法继续工作。 我不会在内部使用DoubleBigDecimal ,只要我的方法继续返回Double (例如)。

不,从某种意义上说,它们并不是更“安全”,尽管有些(非常糟糕的)Java书籍试图以这种方式解释private 。 如果攻击者能够在您的进程中运行任意Java代码,那么所有“安全性”都已消失。 正如另一个已经提到的答案,reflection可以绕过private访问修饰符。

private并不是真正的安全性,因为reflection可以绕过它(modulo classloader / secure classloader stuff)。 它可以作为意图的指示,也可以作为一种编程错误的障碍。

但考虑第三方API – API用户甚至看不到 private属性或方法。 它不仅仅是关于您自己的代码,而是关于哪些代码暴露给他人。 (再次从“我不打算闯入代码”的角度来看待它。)

就安全性而言,答案是“不是真的”:坚定的黑客可以到你的私人领域,并通过一点反思来调用你的私人职能; 他们需要的只是一个包含代码的JAR。

虽然隐藏“敏感”信息并不能使您的课程更安全 ,但它(以及由其构建的系统)使其更易于维护 。 因此,这个答案不是让所有class级成员公开的借口。

我总体上同意到目前为止的答案(即private实际上是代码卫生而不是真正的安全性)。 各种答案都指出你可以使用reflection绕过private 。 请注意,如果启用Java SecurityManager,则可以禁用reflection。 特别参见ReflectPermission 。 但是,很少使用安全管理器(在正常的浏览器沙盒之外)。

显然,只要你遵守开放封闭原则,将所有内容设为私有的原则才适用,否则,如果人们习惯于编辑现有类的内部而不是扩展它们的想法,那么很可能会改变私有成员变量的封装。它通过mutators和accessors访问它们或更改访问修饰符。

我认为你的导师说“安全”的意思不是要让黑客远离黑客,而是要防止黑客入侵。 通过使所有内容尽可能私密,您可以限制一个类在没有它知道的情况下与另一个类混淆的方式。 这是模块化编程的一个例子。

顺便说一句:Java中的reflection实际上允许您覆盖对象字段的访问修饰符。 请参阅javadoc和示例 。