Java 为什么可变字符串会导致安全问题?

Java 为什么可变字符串会导致安全问题?,java,string,immutability,Java,String,Immutability,我看到了另一个人的回答: 字符串已被广泛用作许多java类的参数,例如用于打开网络连接、打开数据库连接、打开文件。若字符串不是不可变的,这将导致严重的安全威胁 我认为在使用前检查字符串可以解决问题。为什么字符串被设计成不可变的呢 谁能给我一个具体的代码示例 您链接到该帖子的更多链接的帖子,其中对该问题进行了更详细的解释: 一般来说,当值不变时,编写和检查敏感代码会更容易,因为 可能影响结果的操作交错较少 想象一下代码 void doSomethingImportant(String name)

我看到了另一个人的回答:

字符串已被广泛用作许多java类的参数,例如用于打开网络连接、打开数据库连接、打开文件。若字符串不是不可变的,这将导致严重的安全威胁


我认为在使用前检查字符串可以解决问题。为什么字符串被设计成不可变的呢


谁能给我一个具体的代码示例

您链接到该帖子的更多链接的帖子,其中对该问题进行了更详细的解释:


一般来说,当值不变时,编写和检查敏感代码会更容易,因为 可能影响结果的操作交错较少

想象一下代码

void doSomethingImportant(String name) {
  if (!isAlphaNumeric(name)) { throw new IllegalArgumentException(); }
  Object o = lookupThingy(name);
  // No chance of SQL-Injection because name is alpha-numeric.
  connection.executeStatement("INSERT INTO MyTable (column) VALUES ('" + name + "')");
}
代码会执行一些检查以防止权限升级,但只有在调用
executeStatement
的参数时,
isAlphaNumeric(name)
为true时,此检查才有效

如果前两个语句被重新排序,那么这就不会是问题,因此不安全感部分来自于错误的交错。但其他代码可能会调用此函数,并假定
name
未被它更改,因此可能必须执行并重新执行有效性检查

如果
String
不是不可变的,那么它可能已被
lookupThingy
更改。为了确保安全检查工作正常,需要正确执行大量代码才能确保此代码不受SQL注入的影响

不仅需要正确执行的代码量更大,而且对一个函数进行本地更改的维护人员可能会影响到其他函数的安全性。非局部效应使代码维护变得困难。维护安全属性总是很危险的,因为安全漏洞很少明显,所以随着时间的推移,易变性可能会导致安全性下降


为什么字符串被设计成不可变的呢

这与为什么它在安全方面不好是分开的

人们普遍认为,使用具有现成不可变字符串类型的语言编写的程序比不使用不必要的缓冲区拷贝的程序要少。不必要的缓冲区拷贝会消耗内存,导致GC搅动,并可能导致对大输入的简单操作比对小输入的操作执行得更差


人们还普遍认为,当使用不可变字符串时,编写正确的程序更容易,因为您不太可能无法防御地复制缓冲区。

这是本书中最古老的安全欺骗:向操作系统提供一些parm,让它验证parm,然后在操作系统引用parm时更新parm,因此,它将做一些不同于它所证实的事情

这在60年代被用来打破IBM OS/360:要请求磁盘I/O,您需要向操作系统传递一个“通道程序”,其中包含磁盘地址、内存地址和其他内容。操作系统将检查磁盘和内存地址是否是您被授权的位置,然后将“通道程序”传递给要执行的I/O通道硬件,而不首先制作本地副本。对时间进行计时并不困难,这样您就可以在检查通道程序后但在I/O通道硬件执行之前修改它,从而允许访问未经授权的磁盘和内存

(请记住,在这段时间内,内存非常宝贵,因此不复制频道程序节省了大量内存。但一旦人们知道了利用它的方法,这个漏洞很快就被堵塞了。)


(当然,我们必须质疑,任何Objective-C程序是否可以被视为在同一进程中运行的其他代码的“安全性”。Objective-C的“duck-typing”特性使真正的安全性充其量不太可能实现。使用不可变字符串更能防止意外修改,而不是恶意修改。)

“我认为在使用前检查字符串可以解决问题“除非您显式使用某种锁,否则不会。如果实现不正确,是什么阻止违规者更改支票的引用?字符串被设计为不可变的原因很多,请这样理解不可变:当一个类在本质上是独立的和完全具体的。或者更糟,也许这个字符串对另一个线程是可见的,它可以在完整性检查和使用之间更改它的值——即使没有一个明确的中间调用!