String
aが不変であることを知りました。その背後にある理由を読んでいたときに、いくつかの理由が浮かびました。たとえば、パフォーマンスが向上したり、値を変更できないため、複数のスレッドで共有したりできます。私が理解しているこれらの理由。
しかし、それがセキュリティとどのように関連しているかはわかりません。String
不変であることは、Javaセキュリティにどのように役立ちますか?
クラスライブラリを作成する際の非常に一般的な方法は、APIに渡されたパラメータを、たとえばコンストラクタに次のように格納することです。
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;
}
}
String
変更可能である場合、これは微妙な悪用につながります。攻撃者は適切なURLを渡し、数マイクロ秒待ってから、攻撃サイトを指すようにURLを設定します。
コピーせずに保存することはかなり一般的な方法であり、文字列は最も一般的に使用されるデータ型の1つであるため、文字列を変更可能のままにしておくと、まだ書き込まれていない多くのAPIが開かれ、深刻なセキュリティ問題が発生します。文字列を不変にすることで、まだ作成されていないAPIを含む、すべてのAPIのこの特定のセキュリティホールが閉じられます。
SecurityManagerの概念が機能するには、不変の文字列が必要です。dasbklinkenlightはすでに彼の答えで正しい方向に進んでいますが、可変の文字列はサンドボックスの概念を完全に壊してしまいます。
たとえばnew FileInputStream("foo");
、ファイルを読み取るためにを実行すると、API実装は内部的に次のことを実行します。
呼び出し元がこれらの2つのステップの間で文字列を変更できる場合、実際には別のファイルが開かれている間に、1つのファイルのセキュリティチェックが成功する可能性があります。
文字列は不変です。つまり、オブジェクト自体は変更できませんが、もちろん参照は変更できます。(たとえば)a = "ty"を呼び出すと、実際には、文字列リテラル"ty"によって作成された新しいオブジェクトへのaの参照が変更されます。オブジェクトを変更するということは、そのメソッドを使用してそのフィールドの1つを変更することを意味します。次に例を示します。
Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"
Stringなどの不変クラス(finalとして宣言されている)では、現在の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"