web-dev-qa-db-fra.com

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

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

Mais je pensais que Java la réflexion peut utiliser pour briser cette règle. Considérez le cas suivant:

public class ProtectedPrivacy{

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

}  

Maintenant, à partir 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 que la méthode encore privée était sûre car pour faire quelque chose comme ci-dessus, nous devons connaître le nom de la méthode. Mais si une classe qui contient une méthode privée écrite par quelqu'un d'autre, nous n'en avons pas la visibilité.

Mais mon point devient invalide depuis la ligne de code ci-dessous.

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

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

Je cite un point de Documentation Java pour clarifier ma question.

Conseils pour choisir 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 y aider. 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.

Cela dépend de ce que vous entendez par "sûr". Si vous utilisez un gestionnaire de sécurité qui autorise ce genre de choses, alors oui, vous pouvez faire toutes sortes de choses désagréables avec réflexion. Mais alors, dans ce type 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-ci - vous faites effectivement confiance au code pour bien jouer. Si vous ne pas faites confiance au code que vous exécutez, vous devez utiliser un gestionnaire de sécurité plus restrictif.

95
Jon Skeet

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 algorithmes, c'est pour protéger les gens de l'obligation de connaître vos données et algorithmes. C'est pourquoi le modificateur par défaut est package - s'ils travaillent sur le package, ils doivent probablement déjà le savoir.

Parallèlement à 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é sur 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) parce que ça ne leur fait rien de bien de le savoir.

Les modificateurs d'accès peuvent être résumés dans une simple phrase "TMI, mec, I donc n'avait pas besoin de le savoir".

40
jmoreno

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

7
Arsen Alexanyan

La question est de savoir qui essayez-vous de enregistrer à partir de. À mon avis, un tel client de votre code est celui à perte ici.

Tout morceau de code (écrit par vous ou par d'autres) qui essaie d'accéder à un membre private de la classe ci-dessus est en train de creuser son propre Grave. private les membres ne font pas partie de l'API public et sont sujets à changement sans préavis. Si un client consomme 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é.

6
Regnidorhcs

private n'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 souhaitez éventuellement que le code s'exécute sur un ordinateur. Même la compilation en binaire est un niveau d'obscurcissement.

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 du côté serveur.

5
Manishearth

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

Le modificateur privé est fourni/utilisé 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 signifie pas que vous ne devez pas utiliser le mode privé - ou ils ne sont pas sûrs. Il s'agit d'utiliser les choses judicieusement ou de manière constructive (comme la réflexion).

5
Raúl

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 évolutive dans votre code. Vos fonctions privées peuvent être considérées comme un détail d'implémentation et peuvent changer au fil du temps, elles ne sont donc pas sûres à 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 peuvent cesser de fonctionner avec les futures versions de votre code.

5
robbie_c