6

我无法理解为什么 java 安全编码很重要。例如,为什么将变量声明为私有很重要?我的意思是我知道这将使从类外部访问这些变量变得不可能,但我可以简单地反编译类来获取值。类似地,将一个类定义为 final 将使该类无法子类化。什么时候子类化一个类会对安全造成危险?如果有必要,我可以再次反编译原始类并使用我想要的任何恶意代码重新实现它。当应用程序被用户“信任”时,问题是否会出现?然后人们会以某种方式滥用这种信任吗?基本上我正在寻找的是一个很好的例子,说明为什么应该遵循安全编码准则。

4

7 回答 7

15

编程很难。

如果你定义了严格的 API,不暴露不应该暴露的变量(我们喜欢称之为封装),你可以帮助你的 API 的用户,从而使编程更容易。这被认为是一件好事。

原因主要不是“安全性”,如将秘密事物保密,而是清晰、简单和易于理解。

作为奖励,如果您知道 API 的用户没有在您背后更改“您的”变量,那么使事情正常工作会容易得多,当然。

于 2009-05-12T07:50:11.557 回答
4

它是“安全的”,意味着类内部工作对任何使用它的人都是隐藏的。

术语安全不是在“保护服务器”中使用的,用于表示一个类的用户不必担心该类将如何执行他想要的任务。

以你为例:

暴露一个类的变量会让你的类的用户知道他们的存在,这是你不想要的,例如:你只需按下一个按钮来打开灯,你现在不需要在里面是铜还是执行任务所需的其他东西。

于 2009-05-12T07:51:53.833 回答
4

Java 是一门面向对象的编程语言,而面向对象编程的关键概念之一就是封装

封装背后的想法是“隐藏”实现细节,例如保存对象状态的内部变量和算法等内部工作,只提供其他对象可以使用的接口,以便与对象执行功能.

使用这个概念,人们想通过使用private变量来隐藏内部状态,以防止其他对象直接影响内部状态。在 Java 中,通常会看到 getter 和 setter(例如getColorsetColor)来处理对象。

此外,封装也可以增加代码的健壮性。

例如,通过限制对内部状态的访问,可以在更改对象之前执行一些健全性检查。

作为一个可靠的例子,假设有一个Score对象的percent值介于0和之间100。通过提供一种setPercent(int)验证指定值是否在允许范围内的方法,可以防止将Score对象设置为不可接受的状态。

因此,如果方法导致错误或如果指定的值不可接受,则尝试通过编写类似语句来直接操作内部状态score.percent = 150是可以避免的。setPercentException

于 2009-05-12T08:07:53.307 回答
3

这里有两个问题。

第一次将变量声明为受保护或私有时,它们不会成为您的公共 API 的一部分。未来其他类可能取决于您的类,如果您想包含新功能、提高性能等,请尽可能自由地进行更改。如果您的所有价值观都是公开的,而不是您内部的所有价值观价值观和机制是公开的。更改它们可能会破坏其他依赖于您的课程。

第二,当暴露变量时,它允许其他类改变你的值。如果他们改变了你的内部价值观,可能会破坏你的程序,并产生奇怪的意外行为。如果您创建的系统依赖于您的类的准确性能,并且内部值发生了变化,那么您将无法再依赖该系统。子类化使这更加复杂。您的系统可能依赖某个特定类型的类来执行预期的操作。通过子类化,可以创建一个看起来是相同类型但不执行预期操作的新类。

例如,如果您有一个带有受保护函数 getArea() 的类 square,您希望返回正方形的面积。但是,可以创建一个扩展正方形的新类,例如矩形类扩展正方形。现在rectange 可以覆盖getArea(),但它仍然是square 类型,这可能会破坏一些依赖于square 功能的东西。通过使您的课程成为最终课程,您断言这永远不会在您的系统中发生。

这种类型的“安全编码”不会阻止别人看到你的源代码,但它有助于使你的代码在未来更加可靠和可用。

于 2009-05-12T08:07:24.477 回答
1

只是补充一下其他人已经说过的话:其中一些功能也可以简单地视为一种表达意图的方式。如果我创建一个成员private,我会让其他人“不可能”访问它(这是可能的,但这不是这里的重点),但更重要的是我告诉用户这是一个实现细节,他们不应该依赖它。

于 2009-05-12T07:55:19.753 回答
1

想象一下,如果您的对象具有非私有(隐藏)的内部属性,并且您访问此属性的代码恰好在多线程环境中运行,因此 N 个线程将同时开始访问它,5 个线程想更改此属性,4 个到读。您无法确保事情会整齐地运行,两个线程都不知道它当前保存了哪些数据,并且它是否成功地更改了该对象的属性。

您将必须编写一段特殊的代码,该代码将负责处理同步访问,但这仍然不能保证您的代码将正常工作,因为您仍然必须检查程序中访问该属性的其余 680 个类而不是直接访问它.

简而言之,您遇到了一个大问题,调试是一场噩梦,因为您不知道数据何时被更改,哪个线程执行此操作,从何处发生等。

如果您不封装,这只是发生的一种情况......

好东西,你的代码运行速度快了 1%,堆栈上的负载更少,你已经获得了可能微不足道的性能提升,你将付出系统周期性崩溃和成功调试的小机会。

于 2009-05-12T10:03:01.997 回答
1

术语“安全编码”是指构建明显试图避免安全漏洞的软件,无论是 C、Java、Ruby、汇编语言还是其他任何语言。在选择安全的语言系统之后,其中最核心的部分可能是保持良好的编程实践。如果一个程序不清楚,那么你几乎没有机会相信它。

对于 Java,有两个值得注意的指南:

在 Java 中有两种不同的安全编码模式。

一方面,您正在处理的代码可能不具备您的代码所具有的所有特权。例如,如果您正在编写库或签名代码,则需要这样做。恶意代码应该不可能以意想不到的方式利用您的权限。这是困难的!

更常见的是,您正在处理仅处理不受信任数据的程序。例如,Web 服务器(想想 XSS 和 SQL 注入)和处理不受信任文件的桌面应用程序(通常问题在于 C 代码具有缓冲区溢出 - 真正的 C++ 更好)。在某些情况下,拒绝服务 (DoS) 可能是一个严重的问题。

有一些重叠。例如,解释器以解释器代码的权限运行,并且可能非常“强大”。

于 2009-05-12T10:07:22.003 回答