La réflexion est-elle un inconvénient car les variables privées ne peuvent pas être restreintes?

14

Le privatemodificateur est utilisé pour restreindre l'accès en dehors de la classe, mais en utilisant la réflexion, d'autres classes peuvent accéder à des méthodes et des champs privés. Je me demande donc comment nous pouvons restreindre l'accessibilité si cela fait partie des exigences.

user245930
la source
2
Le code à faible confiance ne peut pas utiliser la réflexion privée (du moins pas sur d'autres assemblys, j'ai oublié les détails). Le code de confiance totale peut simplement utiliser des pointeurs pour contourner toutes les restrictions du processus.
CodesInChaos
55
Les modificateurs d'accès privés existent principalement pour dire aux programmeurs "ne l'utilisez pas de l'extérieur de la classe, et si vous le faites vraiment, ne vous plaignez pas si la prochaine version casse votre code" pas comme une fonctionnalité de sécurité strictement appliquée.
CodesInChaos
4
Les utilisateurs peuvent également simplement corriger votre code pour faire ce qu'ils veulent. À l'exception partielle de DRM (qui n'est pas assez puissant pour fournir une protection durable), toute personne ayant accès à votre application (binaires ou code source) peut tout faire avec.
Brian
6
N'est-ce pas une question spécifique à la langue? La réflexion fonctionne différemment dans différentes langues. Je me demande si cette question devrait avoir une balise pour Java ou autre chose.
Wayne Conrad

Réponses:

54

Le but des modificateurs d'accès est d'informer les développeurs qui écrivent du code sur ce qu'est l'interface publique d'une classe. Ils ne sont en aucun cas une mesure de sécurité et ils ne cachent ni ne sécurisent aucune information.

JacquesB
la source
33
Ce n'est pas universellement vrai. Citant Eric Lippert , "Les modificateurs d'accès dans le CLR sont des fonctionnalités de sécurité. Les règles d'accès sont complètement confondues avec les systèmes de sécurité et de sécurité de type." En C #, Reflection n'est disponible que pour le code s'exécutant en toute confiance. Cela ne s'applique pas (et ne peut pas) s'appliquer aux utilisateurs malveillants du système qui exécutent le code. Cependant, il s'applique aux plug-ins malveillants.
Brian
5
@Brian Lorsque le problème mentionné par Brian est pertinent, c'est lorsqu'un système permet à du code tiers de s'exécuter sans lui faire entièrement confiance. Les exemples incluent les bacs à sable du navigateur (par exemple l'applet très détesté), le moteur d'application Google et Azure . Il serait vraiment stupide pour Azure de permettre au code non fiable d'explorer les détails des bibliothèques principales de la plate-forme.
JimmyJames
3
@Brian Ce n'est pas correct à 100% - vous pouvez effectuer certaines opérations de réflexion dans du code partiellement fiable; cela ne vous permet tout simplement pas d'accéder à des champs privés.
Luaan
1
@Brian Jusqu'à ce que quelqu'un trouve une vulnérabilité ou une ingénierie sociale qui lui permet de contourner les restrictions. Il ne sert à rien d'essayer de les utiliser de cette façon. Ce n'est pas leur objectif principal.
jpmc26
31

Pour citer Herb Sutter sur les droits d'accès aux cours :

"La question ici est de se protéger contre Murphy contre se protéger contre Machiavel ... c'est-à-dire, se protéger contre les abus accidentels (ce que le langage fait très bien) contre se protéger contre les abus délibérés (ce qui est effectivement impossible). En fin de compte, si un programmeur veut assez pour renverser le système, il trouvera un moyen "

Nemanja Trifunovic
la source
2
Il y a des moments où vous devez sandboxer du code non fiable, mais c'est une tâche intimidante. La protection contre l'erreur (Murphy) est le cas le plus courant.
Paul Draper du
#define private public(en ignorant qu'il s'agit en fait d'un comportement indéfini) et le tour est joué j'ai un accès complet de l'extérieur à la partie restreinte de vos cours.
bolov
La protection contre les abus délibérés peut être théoriquement impossible mais elle est effectivement possible, en rendant les abus suffisamment difficiles pour qu'ils se produisent très rarement. Il est important d'être clair à ce sujet. Sinon, le logiciel ne pourrait pas être utilisé du tout dans des situations telles que des dispositifs médicaux vitaux.
MarkJ
@MarkJ. La remarque de Herb Sutter concerne l'abus délibéré par le développeur qui a écrit la classe en premier lieu et peut-être ses coéquipiers. Je ne pense pas qu'il existe un moyen d'empêcher ce genre d'abus par les fonctionnalités linguistiques.
Nemanja Trifunovic
@bolov, cette cascade dépend de la langue, je pense. Alors que les préprocesseurs C / C ++ vous permettraient probablement de vous en sortir, tout ce qui sans eux donnerait probablement une erreur "ne peut pas utiliser de mots réservés dans une # définition".
Dan est en train de jouer par Firelight le
10

Non, c'est en fait un avantage important. Tout simplement parce que certains développeurs ne considéraient pas que quiconque aurait besoin d'accéder à un élément d'état interne ne signifie pas qu'aucun cas d'utilisation légitime ne se présenterait jamais. Dans ces cas, l'utilisation de la réflexion pour effectuer une intervention chirurgicale sur un objet peut être un dernier recours. J'ai dû utiliser cette technique plus d'une fois.

Mason Wheeler
la source
1
En d'autres termes, c'est un moyen de contourner une API probablement cassée - que ce soit en raison d'exigences incomplètes ou d'une implémentation incomplète.
Rétablir Monica
4

Vous restreignez encore plus l'accessibilité en remontant d'un niveau: l'environnement d'exécution.

Tous les langages n'ont pas ce concept, mais au moins avec Java, vous pouvez utiliser un gestionnaire de sécurité qui interdit de rendre les champs privés accessibles. Vous pouvez installer manuellement le gestionnaire de sécurité au moment de l'exécution ou ajouter une politique de sécurité dans un fichier jar qui est ensuite scellé pour empêcher toute modification.

Plus d'informations sur cette opération en Java: Reflection Security

Communauté
la source
3

De quelle réflexion parlez-vous?

Dans de nombreux systèmes de réflexion, le contournement de l'encapsulation est une capacité explicite que votre code doit obtenir, et n'a pas par défaut.

Si vous êtes préoccupé par l'encapsulation, la solution simple est simplement de ne pas utiliser un système de réflexion qui ne le préserve pas.

Jörg W Mittag
la source
3

En Python, il n'y a pas de modificateurs d'accès. La convention consiste à préfixer par un trait de soulignement les méthodes et les variables qui ne devraient pas être accessibles depuis l'extérieur de la classe. Est-ce que cela vous empêche techniquement d'accéder à ce champ à partir d'une classe tierce? Pas du tout; mais si vous le faites, vous êtes seul et vous prenez le risque de casser quelque chose, sans pouvoir blâmer l'autre classe.

En C #, les modificateurs d'accès existent, mais ils ne sont encore qu'une convention - celle qui est appliquée par un compilateur, mais toujours une convention. Cela signifie que techniquement, on peut toujours accéder et modifier des variables privées, soit par le biais de Reflection, soit en altérant directement la mémoire (comme le font les entraîneurs de jeux ). La conséquence est exactement la même: si les variables de votre classe sont modifiées par la réflexion d'une autre classe, ou par l'altération de la mémoire par une autre application, et que cela casse quelque chose dans votre classe, ce n'est pas votre faute.

Notez que cela, évidemment, crée des problèmes de sécurité où un tiers peut accéder à vos données; quelque chose qui conduit à des variantes cryptées d'une chaîne et à des structures de données similaires. Mais la protection de votre code contre une telle utilisation est davantage liée aux restrictions d'accès au niveau du système d'exploitation et du code , et n'a rien à voir avec Reflection en soi.

Arseni Mourzenko
la source
2
Notez qu'en C #, seul le code entièrement fiable peut refléter les membres privés. L'écriture directe pour traiter la mémoire fonctionne toujours, mais est plus difficile que dans le code natif.
Luaan