Ist Reflection ein Nachteil, da private Variablen nicht eingeschränkt werden können?

14

Der privateModifikator wird verwendet, um den Zugriff außerhalb der Klasse einzuschränken, aber mithilfe der Reflektion können andere Klassen auf private Methoden und Felder zugreifen. Ich frage mich daher, wie wir die Zugänglichkeit einschränken können, wenn dies Teil der Anforderung ist.

user245930
quelle
2
Code mit geringer Vertrauenswürdigkeit kann keine private Reflektion verwenden (zumindest nicht bei anderen Assemblys, ich habe die Details vergessen). Voller Vertrauenscode kann einfach Zeiger verwenden, um Einschränkungen innerhalb des Prozesses zu umgehen.
CodesInChaos
55
Private Zugriffsmodifikatoren dienen in erster Linie dazu, Programmierern mitzuteilen, dass "dies nicht von außerhalb der Klasse verwendet wird, und wenn Sie dies wirklich tun, sollten Sie sich nicht beschweren, wenn die nächste Version Ihren Code beschädigt", da diese Sicherheitsfunktion nicht streng genug durchgesetzt wird.
CodesInChaos
4
Benutzer können Ihren Code auch einfach patchen, um zu tun, was sie wollen. Mit einer teilweisen Ausnahme für DRM (das nicht leistungsfähig genug ist, um dauerhaften Schutz zu bieten) kann jeder, der Zugriff auf Ihre Anwendung (Binärdateien oder Quellcode) hat, alles damit tun.
Brian
6
Ist das nicht eine sprachspezifische Frage? Reflexion funktioniert in verschiedenen Sprachen unterschiedlich. Ich frage mich, ob diese Frage ein Tag für Java oder etwas anderes haben sollte.
Wayne Conrad

Antworten:

54

Der Zweck von Zugriffsmodifikatoren besteht darin, Entwickler, die Code schreiben, über die öffentliche Schnittstelle einer Klasse zu informieren. Sie stellen in keiner Weise eine Sicherheitsmaßnahme dar und verbergen oder sichern keine Informationen im wahrsten Sinne des Wortes.

JacquesB
quelle
33
Dies ist nicht allgemeingültig. Eric Lippert zitiert : "Zugriffsmodifikatoren in der CLR sind Sicherheitsfunktionen. Die Regeln für den Zugriff sind eng mit den Sicherheits- und Typensicherungssystemen verknüpft ." In C # ist Reflection nur für Code verfügbar, der unter voller Vertrauenswürdigkeit ausgeführt wird. Dies gilt nicht (und kann nicht) für böswillige Benutzer des Systems, die den Code ausführen. Es gilt jedoch für böswillige Plug-Ins.
Brian
5
@Brian Das Problem, von dem Brian spricht, ist, wenn ein System zulässt, dass Code von Drittanbietern ausgeführt wird, ohne ihm vollständig zu vertrauen. Beispiele hierfür sind Browsersandboxen (z. B. das verhasste Applet), die Google App Engine und Azure . Es wäre wirklich dumm von Azure, nicht vertrauenswürdigem Code zu erlauben, die Details der Kernbibliotheken der Plattform zu untersuchen.
JimmyJames
3
@Brian Das ist nicht 100% richtig - es gibt einige Reflektionsoperationen, die Sie in teilweise vertrauenswürdigem Code ausführen können. Es erlaubt Ihnen einfach nicht, auf private Felder zuzugreifen.
Luaan
1
@Brian Bis jemand eine Schwachstelle oder ein Social Engineering findet, mit dem er die Einschränkungen umgehen kann. Es macht keinen Sinn, sie so zu benutzen. Das ist nicht ihr Hauptzweck.
jpmc26
31

So zitieren Sie Herb Sutter zu Zugriffsrechten für Klassen :

"Hier geht es darum, vor Murphy zu schützen und vor Machiavelli zu schützen ... das heißt, vor versehentlichem Missbrauch zu schützen (was die Sprache sehr gut kann) und vor vorsätzlichem Missbrauch zu schützen (was praktisch unmöglich ist) Ein Programmierer möchte unbedingt das System untergraben, er wird einen Weg finden. "

Nemanja Trifunovic
quelle
2
Es gibt Zeiten, in denen Sie nicht vertrauenswürdigen Code sandboxen müssen, aber das ist eine entmutigende Aufgabe. Schutz vor Fehlern (Murphy) ist der weitaus häufigere Fall.
Paul Draper
#define private public(ignoriert, dass es sich tatsächlich um Undefiniertes Verhalten handelt) und voila Ich habe von außen vollen Zugriff auf den eingeschränkten Teil Ihrer Klassen.
Bolov
Der Schutz vor vorsätzlichem Missbrauch mag theoretisch unmöglich sein, ist aber effektiv möglich, indem Missbrauch so erschwert wird, dass er sehr selten vorkommt. Es ist wichtig, darüber klar zu sein. Andernfalls könnte Software in Situationen wie lebenswichtigen medizinischen Geräten überhaupt nicht verwendet werden.
MarkJ
@MarkJ. In Herb Sutters Bemerkung geht es um vorsätzlichen Missbrauch durch den Entwickler, der die Klasse überhaupt geschrieben hat, und möglicherweise durch seine Teamkollegen. Ich glaube nicht, dass es einen Weg gibt, diese Art von Missbrauch durch Sprachmerkmale zu verhindern.
Nemanja Trifunovic
@ Bolov, dieser Stunt ist sprachabhängig, denke ich. Während C / C ++ - Präprozessoren Sie wahrscheinlich davonkommen lassen würden, würde alles ohne sie wahrscheinlich den Fehler "Reservierte Wörter können nicht in einem #define verwendet werden" auslösen.
Dan Neely
10

Nein, das ist eigentlich ein wichtiger Vorteil. Nur weil einige Entwickler nicht der Meinung waren, dass jemand Zugriff auf einen Teil des internen Zustands benötigen würde, heißt das nicht, dass kein legitimer Anwendungsfall jemals auftauchen wird. In diesen Fällen kann die Verwendung von Reflection zur Durchführung von Operationen an einem Objekt der letzte Ausweg sein. Ich musste diese Technik mehrmals anwenden.

Mason Wheeler
quelle
Mit anderen Worten, es ist eine Möglichkeit, eine möglicherweise fehlerhafte API zu umgehen - sei es aufgrund unvollständiger Anforderungen oder unvollständiger Implementierung.
Setzen Sie Monica
4

Sie schränken die Zugänglichkeit noch weiter ein, indem Sie eine Ebene höher gehen: die Ausführungsumgebung.

Nicht alle Sprachen haben dieses Konzept, aber zumindest mit Java können Sie einen Sicherheitsmanager verwenden, der es verbietet, private Felder zugänglich zu machen. Sie können den Sicherheitsmanager zur Laufzeit manuell installieren oder eine Sicherheitsrichtlinie in eine JAR-Datei einfügen, die dann versiegelt wird, um Änderungen zu verhindern.

Weitere Informationen dazu in Java: Reflection Security

Gemeinschaft
quelle
3

Über was für ein Spiegelbild sprichst du?

In vielen Reflektionssystemen ist das Umgehen der Kapselung eine explizite Funktion, die Ihr Code erhalten muss und standardmäßig nicht hat.

Wenn Sie sich Gedanken über die Verkapselung machen, besteht die einfache Lösung darin, kein Reflexionssystem zu verwenden, das es nicht bewahrt.

Jörg W. Mittag
quelle
3

In Python gibt es keine Zugriffsmodifikatoren. Die Konvention besteht darin, die Methoden und Variablen, auf die nicht von außerhalb der Klasse zugegriffen werden soll, mit einem Präfix zu versehen. Verhindert es technisch, dass Sie von einer Klasse eines Drittanbieters auf ein solches Feld zugreifen können? Überhaupt nicht; Aber wenn Sie dies tun, sind Sie auf sich allein gestellt und riskieren, etwas zu zerbrechen, ohne die andere Klasse beschuldigen zu können.

In C # sind Zugriffsmodifikatoren vorhanden, es handelt sich jedoch nur um eine Konvention, die von einem Compiler erzwungen wird, aber immer noch eine Konvention ist. Das bedeutet, dass man technisch gesehen immer noch auf private Variablen zugreifen und diese ändern kann, entweder durch Reflection oder durch direkte Manipulation des Speichers (wie bei Spieletrainern) tun). Die Konsequenz ist genau die gleiche: Wenn die Variablen Ihrer Klasse durch Reflection einer anderen Klasse oder durch Manipulation des Speichers durch eine andere Anwendung geändert werden und etwas in Ihrer Klasse beschädigt wird, ist dies nicht Ihre Schuld.

Beachten Sie, dass dies offensichtlich zu Sicherheitsproblemen führt, bei denen ein Dritter auf Ihre Daten zugreifen kann. Dies führt zu verschlüsselten Varianten eines Strings und ähnlichen Datenstrukturen. Der Schutz Ihres Codes vor einer solchen Verwendung ist jedoch eher mit Zugriffsbeschränkungen auf Betriebssystem- und Codeebene verbunden und hat an sich nichts mit Reflection zu tun.

Arseni Mourzenko
quelle
2
Beachten Sie, dass in C # nur vollständig vertrauenswürdiger Code private Mitglieder widerspiegeln kann. Das direkte Schreiben in den Verarbeitungsspeicher funktioniert weiterhin, ist jedoch schwieriger als im nativen Code.
Luaan