Sonntag, 7. September 2008
Wie privat ist private eigentlich wirklich?
developer, 20:59h
In so gut wie jeder Einsteigerlektüre für die Sprache Java wird gelehrt, dass Datenkapselung mit eine der wichtigsten Voraussetzungen für eine saubere, objetorientierte Programmierung ist. In der Regel genügt es den Autoren darauf hinzuweisen, dass Attribute als
Da Java über das Feature der Reflection vefügt, ist es möglich, sich hierüber Informationen über die Methoden und eben auch Attribute einzelner Klassen zu informieren. - Dazu gehören natürlich auch diejenigen, die als
Angenommen, wir interessieren uns für den Inhalt des als
Auf obige Weise erlang man natürlich erst generelle Informationen über das Attribut
In der Standardkonfiguration wird ein solcher Zugriff allerdings mit dem Auftreten einer
So ist es nun nicht nur möglich, den Inhalt des eigentlich versteckten Arrays auszulesen, sondern, da die Inhalte eines Arrays anders als ein Array selbst nicht als
Die Ausgabe ist nun, nicht wie erwartet "Hans" sondern hat sich zu "Haus" verändern. Das Objekt vom Typ
Eine totale Katastrophe ist dies für das Sichheitskonzept der Sprache Java natürlich nicht, denn durch setzen der "
private
oder protected
deklariert und nur über entsprechende Zugriffsmethoden nach außen zum Lesen oder ggf. auch Schreiben erreichbar gemacht werden sollen. - Wenn man sich die Sprache Java etwas genauer ansieht, reicht dies allerdings leider nicht immer aus...Da Java über das Feature der Reflection vefügt, ist es möglich, sich hierüber Informationen über die Methoden und eben auch Attribute einzelner Klassen zu informieren. - Dazu gehören natürlich auch diejenigen, die als
private
oder protected
deklariert sind.Angenommen, wir interessieren uns für den Inhalt des als
private
deklarierten Attributs value
der Klasse String
(auch wenn man da zugegebenermaßen auch einfacher dran kommen kann). Dann ist es möglich, eine Referenz auf dieses Attribut mit Hilfe der Methoden der Reflection-API zu erlangen:
String st = "Hans";
Class<? extends String> stringClass = st.getClass();
Field valueField = stringClass.getDeclaredField("value");
Class<? extends String> stringClass = st.getClass();
Field valueField = stringClass.getDeclaredField("value");
Auf obige Weise erlang man natürlich erst generelle Informationen über das Attribut
value
, nicht allerdings den Inhalt des Attributs einer konkreten String
-Instanz. Doch auch hier ist die Reflection-API hilfreich:
char[] value = (char[])valueField.get(st);
In der Standardkonfiguration wird ein solcher Zugriff allerdings mit dem Auftreten einer
IllegalAccessException
quittiert, was uns also noch nicht wirklich zu dem gewünschten Inhalt führt. - Hierzu ist noch eine kleine Veränderung notwendig. Über die Methode setAccessible
des Field
-Objetks ist es nämlich möglich, genau dieses prüfende Verhalten der Methode Field.get(Object)
auszuschalten:
valueField.setAccessible(true);
char[] value = (char[])valueField.get(st);
System.out.println(Arrays.toString(value));
char[] value = (char[])valueField.get(st);
System.out.println(Arrays.toString(value));
So ist es nun nicht nur möglich, den Inhalt des eigentlich versteckten Arrays auszulesen, sondern, da die Inhalte eines Arrays anders als ein Array selbst nicht als
final
deklariert werden können, denInhalt des Arrays auch zu verändern:
value[2] = 'u';
System.out.println(st);
System.out.println(st);
Die Ausgabe ist nun, nicht wie erwartet "Hans" sondern hat sich zu "Haus" verändern. Das Objekt vom Typ
String
, welches theoretisch zwar unveränderbar sein sollte, ist über einen kleinen Umweg auf einmal doch veränderbar geworden...Eine totale Katastrophe ist dies für das Sichheitskonzept der Sprache Java natürlich nicht, denn durch setzen der "
suppressAccessChecks
"-Permission innerhalb des zuständigen SecurityManagers
kann genau die für den Zugriff notwendige Field.setAccessible
-Methode verboten werden. - Klar ist allerdings auch, dass die meisten (auch serverseitig eingestzten) Java-Umgebungen mit den Standardeinstellungen laufen, in denen gerade genau diese Änderung am SecurityManager
nicht vorgenommen wurde...... comment