Les méthodes privées sont-elles vraiment sûres?


92

En Java, le privatemodificateur d'accès est considéré comme sûr car il n'est pas visible en dehors de la classe. Alors le monde extérieur ne connaît pas non plus cette méthode.

Mais je pensais que la réflexion Java pouvait servir à enfreindre cette règle. Considérez le cas suivant:

public class ProtectedPrivacy{

  private String getInfo(){
     return "confidential"; 
  }

}  

Maintenant, d'une autre classe, je vais obtenir des informations:

public class BreakPrivacy{

   public static void main(String[] args) throws Exception {
       ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy();
       Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null);
       method.setAccessible(true);
       Object result = method.invoke(protectedPrivacy);
       System.out.println(result.toString());
   }
} 

En ce moment, je pensais juste que la méthode privée était toujours sûre car pour faire quelque chose comme ci-dessus, nous devons connaître le nom de la méthode. Mais si une classe contient une méthode privée écrite par quelqu'un d'autre, nous n'avons pas de visibilité sur celles-ci.

Mais mon point est devenu invalide car en dessous de la ligne de code.

Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();

Maintenant, cela method[]contient toutes les choses à faire ci-dessus. Ma question est la suivante: y a-t-il un moyen d'éviter ce genre de choses en utilisant la réflexion Java?

Je cite un point de la documentation Java pour clarifier ma question.

Conseils sur le choix d'un niveau d'accès:

Si d'autres programmeurs utilisent votre classe, vous voulez vous assurer que les erreurs de mauvaise utilisation ne peuvent pas se produire. Les niveaux d'accès peuvent vous aider à le faire. Utilisez le niveau d'accès le plus restrictif qui a du sens pour un membre particulier. Utilisez privé sauf si vous avez une bonne raison de ne pas le faire.


1
L'utilisation d'un obfuscateur peut aider, car getDeclaredMethodsrenverrait des noms qui ressemblent à des déchets.
dasblinkenlight

213
Privé, public protégé, etc. n'est pas pour la sécurité, c'est pour éviter que les gens bien intentionnés ne commettent des erreurs. Ne l'utilisez pas comme mesure de sécurité
Richard Tingle

20
Le code Java est de toute façon décompilable. Un «attaquant» pourrait simplement télécharger un décompilateur Java et lire votre code, ou changer «privé» en «public».
11684

7
Pour élaborer ce que @RichardTingle a commenté (+1 btw). Il existe une grande et importante différence entre la sécurité et la sûreté. Là où ce dernier est le problème atténué avec les modificateurs d'accès; pour ne pas casser les choses par accident
utilisateur

3
Tout cela est assez clair pour les programmeurs où les modificateurs d'accès n'existent pas, comme en Python. Dans ces langages, privé / public se distingue simplement par une convention dans les noms (en python, tout ce qui commence par un seul trait de soulignement doit être considéré comme privé). Cela rend assez clair que le marquage quelque chose comme « privé » ne pas ajouter une sécurité, mais il est seulement un moyen simple de dire ce que les gens devraient utiliser de votre API. J'ai des doutes sur le fait qu'avoir un compilateur vérifie cela aide du tout car il est vraiment facile de suivre la convention sans aide "externe".
Bakuriu

Réponses:


95

Cela dépend de ce que vous entendez par «sûr». Si vous utilisez un gestionnaire de sécurité qui permet ce genre de chose, alors oui, vous pouvez faire toutes sortes de choses désagréables avec réflexion. Mais dans ce genre d'environnement, la bibliothèque peut probablement être simplement modifiée pour rendre la méthode publique de toute façon.

Le contrôle d'accès est effectivement «consultatif» dans un environnement comme celui-là - vous faites effectivement confiance au code pour bien jouer. Si vous ne faites pas confiance au code que vous exécutez, vous devez utiliser un gestionnaire de sécurité plus restrictif.


3
Tangentiel, je sais, mais pourriez-vous expliquer un peu ce que serait un gestionnaire plus restrictif dans ce sens?
Gris

12
@Gray: Une instance de SecurityManager qui lève des exceptions sur les check*appels pertinents , en gros.
Jon Skeet

40

Les modificateurs d'accès n'ont rien à voir avec la sécurité. En fait, vous pouvez et devez considérer les modificateurs d'accès comme l'inverse de la sécurité - ce n'est pas pour protéger vos données ou vos algorithmes, c'est pour protéger les gens de l'exigence de connaître vos données et vos algorithmes. C'est pourquoi le modificateur par défaut est package - s'ils travaillent sur le package, ils ont probablement déjà besoin de le savoir.

Avec la connaissance des données et des méthodes de votre code, vient la responsabilité de savoir quand et comment l'utiliser. Vous ne mettez pas privé votre méthode inIt pour empêcher quelqu'un de le découvrir, vous le faites parce que (a) ils ne sauront pas que vous n'appelez cela qu'après foo et seulement si bar = 3.1415 et (b) car cela ne leur sert à rien de le savoir.

Les modificateurs d'accès peuvent se résumer en une simple phrase "TMI, mec, je n'avais donc pas besoin de savoir ça".


3
Excellente réponse, mais j'ai eu besoin de google pour savoir que TMI signifiait trop d'informations. Je suppose que j'ai besoin de passer plus de temps dans la vallée :-)
mikelong

7

En disant «sûr», vous vous protégez, vous ou d'autres développeurs, qui utilisent votre API pour ne pas endommager l'objet en appelant votre méthode privée. Mais si vous ou eux avez vraiment besoin d'appeler cette méthode, ils peuvent le faire avec Reflection.


6

La question est de savoir de qui essayez de le sauver . À mon avis, un tel client de votre code est celui qui est perdu ici.

Tout morceau de code (écrit par vous ou par d'autres) qui tente d'accéder à un privatemembre de la classe ci-dessus creuse essentiellement sa propre tombe. privateles membres ne font pas partie de l' API publique et sont susceptibles d'être modifiés sans préavis. Si un client consomme l'un de ces membres privés de la manière indiquée ci-dessus, il se cassera s'il passe à une version plus récente de l'API dans laquelle le membre privé a été modifié.


5

Avec facilité, il y a responsabilité. Il y a des choses que vous ne pouvez pas faire et des choses que vous pouvez faire mais que vous ne devriez pas faire.

Le modificateur privé est fourni / utilisé comme / de la manière la plus restreinte. Les membres qui ne devraient pas être visibles en dehors de la classe seront définis comme privés. Mais cela peut être rompu avec la réflexion comme nous le voyons. Mais cela ne veut pas dire que vous ne devez pas utiliser private - ou ils sont dangereux. Il s'agit d'utiliser les choses judicieusement ou de manière constructive (comme la réflexion).


5

En supposant que vous faites confiance au programmeur client de votre API, une autre façon de voir est de savoir à quel point il est `` sûr '' pour eux d'utiliser ces fonctions particulières.

Vos fonctions accessibles au public doivent fournir une interface claire, bien documentée et rarement changeante dans votre code. Vos fonctions privées peuvent être considérées comme un détail d'implémentation et peuvent changer avec le temps, il n'est donc pas sûr de les utiliser directement.

Si un programmeur client fait tout son possible pour contourner ces abstractions, il déclare en quelque sorte qu'il sait ce qu'il fait. Plus important encore, ils comprennent qu'il n'est pas pris en charge et peut cesser de fonctionner avec les futures versions de votre code.


5

privaten'est pas pour la sécurité, c'est pour garder le code propre et pour éviter les erreurs. Il permet aux utilisateurs de modulariser le code (et comment il est développé) sans avoir à se soucier de tous les détails des autres modules

Une fois que vous avez publié votre code, les gens peuvent comprendre comment cela fonctionne. Il n'y a aucun moyen de "masquer" la logique si vous voulez finalement que le code s'exécute sur un ordinateur. Même la compilation en binaire est jsut un niveau d'obfuscation.

Donc, il n'y a aucun moyen de configurer votre API pour faire des choses spéciales que vous ne voulez pas que les autres puissent appeler. Dans le cas d'une API Web, vous pouvez placer les méthodes que vous souhaitez contrôler côté serveur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.