2013-03-07 13 views
14

Jestem nowicjuszem w Javie i podczas uczenia się natknąłem się na fakt, że String jest niezmienny. Kiedy czytałem przyczynę tego problemu, pojawiło się kilka powodów, na przykład wzrost wydajności, ponieważ jego wartość nie może być modyfikowana i może być współdzielona przez wiele wątków. Z tych powodów rozumiem.
Ale nie rozumiem, jak to jest związane z bezpieczeństwem. Jak niezmienna jest String pomoc w bezpieczeństwie Java?W jaki sposób łańcuch znaków Java jest niezmienny zwiększa bezpieczeństwo?

Proszę mi pomóc w zrozumieniu. Z góry dziękuję.

+2

Gdzie jest napisane, że pomaga to w zapewnieniu bezpieczeństwa? – ivant

+0

możliwy duplikat [Java Inheritance, w jaki sposób rozszerzenie klasy efekt faktycznej klasy] (http://stackoverflow.com/questions/15165619/java-inheritance-how-does-a-extending-a-class-effect- the-actual-class) – jtahlborn

Odpowiedz

15

bardzo częstą praktyką w bibliotekach klasie pisania zapisuje parametry przekazane do swojego API, powiedzmy, w konstruktorze tak:

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; 
    } 
} 

Zmieniono to na String, co doprowadziłoby do subtelnego exploita: atakujący przekazałby dobry URL, poczekał kilka mikrosekund, a następnie ustawił adres URL tak, by wskazywał na atakowaną stronę.

Ponieważ przechowywanie bez kopiowania jest dość powszechną praktyką, a ponieważ łańcuchy są jednym z najczęściej używanych typów danych, pozostawienie łańcuchów zmiennymi otwierałoby wiele interfejsów API, które nie zostały jeszcze napisane na poważny problem z zabezpieczeniami. Tworzenie niezmiennych łańcuchów zamyka tę lukę bezpieczeństwa dla wszystkich interfejsów API, w tym tych, które nie zostały jeszcze napisane.

+1

Dobrym przykładem zmienności ("częściowej") jest "Plik". Zasadniczo jest to po prostu "String". Jednak w wielu przypadkach użyto go do kontroli bezpieczeństwa. Złośliwa podklasa może zmienić sprawdzanie i używanie betwixt (luka TOCTOU/TOC2TOU). –

+1

Nie jestem pewien, jak zostały wykonane subtelne exploity, ale zakładając, że metoda zostanie przechwycona w jakiś sposób przez inny wątek. Zasadniczo, ponieważ String jest niezmienny, jeśli konstruktor MyApi jest wywoływany z urlString "ABC", wówczas zawartość nie może być zmieniona spoza konstruktora. Jeśli nie byłby niezmienny, mógłby zostać zmutowany w drugim wątku po prostu przez wywołanie urlString = "someMaliciousUrl"; po wywołaniu checkApprovedUrl. Czy to zrozumienie jest poprawne? – Mercury

+0

@ Mercury Tak, to jest poprawne zrozumienie opisanego powyżej ataku. – dasblinkenlight

0

Ciąg jest niezmienny oznacza, że ​​nie można zmienić samego obiektu, ale oczywiście można zmienić odniesienie. Kiedy wywołujesz (na przykład) a = "ty", faktycznie zmieniasz odniesienie do nowego obiektu utworzonego przez literał łańcuchowy "ty". Zmiana przedmiotu oznacza wykorzystać swoje metody, aby zmienić jeden ze swoich dziedzinach, na przykład:

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

natomiast w klasie niezmiennej (zadeklarowanego jako ostateczna), na przykład String, nie można zmienić bieżącą String ale można wrócić nowy ciąg, czyli:

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" 
+4

"final" nie oznacza, że ​​jest niezmienny. W przypadku zajęć oznacza to, że nie możesz go odziedziczyć. – ivant

+0

aby być niezmiennym, musisz być ostateczny, aby twoja podklasa nie łamała niezmienności – topcat3

+0

, co może mieć miejsce, ale nie wystarczy zadeklarować, że jest ostateczna, aby stała się niezmienna. – ivant

3

Ciągi niezmienne są wymagane, aby koncepcja programu SecurityManager zadziałała. dasbklinkenlight jest już na właściwej ścieżce z jego odpowiedzią, ale zmienne łańcuchy całkowicie złamałyby koncepcję piaskownicy.

Na przykład, kiedy wykonujesz new FileInputStream("foo"); odczytać plik, wdrożenie API zrobi wewnętrznie między innymi:

  • wywołać metodę checkRead menedżera zabezpieczeń jest z „foo” jako argument i rzucić wyjątek, jeśli czek nie
  • system operacyjny
  • stosowanie domaga się faktycznie otworzyć pliku, jeśli kontrola bezpieczeństwa przeszedł

Jeśli wywołujący jest w stanie zmodyfikować ciąg między tymi dwoma etapami, kontrola bezpieczeństwa może odnieść sukces na jednym plik, podczas gdy faktycznie inny plik zostanie otwarty.

+0

nie jestem pewien czy rozumiem poprawnie Mam wątpliwości od czasu przejścia java przez wartość Kontrola bezpieczeństwa wydarzyła się dla foo tylko foo zostanie otwarta –

Powiązane problemy