17

我刚刚了解到 aString是不可变的。当我阅读它背后的原因时,出现了一些原因,例如性能提高,或者由于它的值不能被修改,它可以被多个线程共享。这些原因我都明白。

但我不明白它与安全性有何关系。String不可变对 Java 安全性有何帮助?

4

3 回答 3

18

A very common practice in writing class libraries is storing the parameters passed into your API, say, in a constructor, like this:

public class MyApi {
    final String myUrl;
    public MyApi(String urlString) {
        // Verify that urlString points to an approved server
        if (!checkApprovedUrl(urlString)) throw new IllegalArgumentException();
        myUrl = urlString;
    }
}

Were String mutable, this would lead to a subtle exploit: an attacker would pass a good URL, wait for a few microseconds, and then set the URL to point to an attack site.

Since storing without copying is a reasonably common practice, and because strings are among the most commonly used data types, leaving strings mutable would open up many APIs that are not written yet open to a serious security problem. Making strings immutable closes this particular security hole for all APIs, including the ones that are not written yet.

于 2013-03-07T15:28:51.353 回答
4

SecurityManager 概念需要不可变的字符串才能工作。dasbklinkenlight 的答案已经走在正确的轨道上,但可变字符串将完全打破沙盒概念。

例如,当您new FileInputStream("foo");读取文件时,API 实现将在内部执行以下操作:

  • 使用“foo”作为参数调用安全管理器的 checkRead 方法,如果检查失败则抛出异常
  • 如果安全检查通过,则使用操作系统调用实际打开文件

如果调用者能够在这两个步骤之间修改字符串,则一个文件的安全检查可能会成功,而实际上将打开另一个文件。

于 2013-03-07T15:39:33.513 回答
0

字符串是不可变的意味着你不能改变对象本身,但你当然可以改变引用。当您调用(例如)a = "ty" 时,实际上是在将 a 的引用更改为由字符串文字 "ty" 创建的新对象。改变一个对象意味着使用它的方法来改变它的一个字段,例如:

Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"

在不可变类(声明为 final)中,例如 String,您不能更改当前 String,但可以返回一个新 String,即:

String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"
于 2013-03-07T15:23:48.980 回答