Являются ли частные методы действительно безопасными?

В Java модификатор доступа private считается безопасным, поскольку он не виден вне класса. Тогда внешний мир не знает об этом методе.

Но я думал, что отражение Java может использовать, чтобы нарушить это правило. Рассмотрим следующий случай:

public class ProtectedPrivacy{

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

}  

Теперь из другого класса я собираюсь получить Info:

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());
   }
} 

В этот момент я просто подумал, что все-таки секретный метод безопасен, так как для того, чтобы сделать что-то вроде выше, мы должны знать имя метода. Но если класс, содержащий частный метод, написанный кем-то другим, у нас нет видимости этих.

Но моя точка становится недействительной после строки кода.

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

Теперь это method[] содержит все, что нужно делать выше. Мой вопрос в том, есть ли способ избежать такого рода вещей, используя отражение Java?

Я процитирую некоторый пункт из Java-документации, чтобы уточнить мой вопрос.

Советы по выбору уровня доступа:

Если другие программисты используют ваш класс, вы хотите убедиться, что ошибки от неправильного использования не может случиться. Уровни доступа могут помочь вам сделать это. Используйте самый ограничительный уровень доступа, который имеет смысл для конкретного член. Используйте конфиденциальность, если у вас нет веских оснований.

+92
источник поделиться
7 ответов

Это зависит от того, что вы подразумеваете под "безопасным". Если вы работаете с менеджером безопасности, который допускает подобные вещи, то да, вы можете делать всевозможные неприятные вещи с отражением. Но тогда в такой среде библиотека, возможно, просто будет изменена, чтобы сделать этот метод общедоступным.

Управление доступом эффективно "консультативно" в такой среде - вы действительно доверяете коду, чтобы играть хорошо. Если вы не доверяете запущенному вами коду, вы должны использовать более ограничительный диспетчер безопасности.

+95
источник

Модификаторы доступа не имеют никакого отношения к безопасности. Фактически вы можете и должны смотреть на модификаторы доступа как на обратную сторону безопасности - это не защита ваших данных или алгоритмов, это защита людей от необходимости знать о ваших данных и алгоритмах. Вот почему модификатор по умолчанию - это пакет - если они работают над пакетом, который, вероятно, уже нужно знать.

Наряду со знанием данных и методов вашего кода возникает способность знать, когда и как его использовать. Вы не ставите частные в свой метод inIt, чтобы кто-то не узнал об этом, потому что (а) они не будут знать, что вы вызываете это только после foo и только если bar = 3.1415 и (b) потому что им нехорошо знать об этом.

Модификаторы доступа можно суммировать в простой фразе "TMI, dude, я , поэтому не нужно было знать это".

+40
источник

Говоря "безопасно", вы защищаете вас или других разработчиков, которые используют ваш API, чтобы не повредить объект, вызвав ваш частный метод. Но если вам или им действительно нужно называть этот метод, они могут сделать это с помощью Reflection.

+7
источник

Вопрос в том, с кем вы пытаетесь его сохранить. На мой взгляд, такой клиент вашего кода является тем, кто потерян здесь.

Любой фрагмент кода (написанный вами или другими лицами), который пытается получить доступ к члену private указанного класса, по сути, выкапывает свою собственную могилу. Члены private не входят в состав публичного API и могут быть изменены без предварительного уведомления. Если клиент использует один из таких частных членов в соответствии с приведенным выше способом, он будет разорван, если он обновится до новой версии API, в которой изменен частный член.

+6
источник

С помощью объекта наступает ответственность. Есть вещи, которые вы не можете делать, а вещи, которые вы можете, но вы не должны делать.

Частный модификатор предоставляется/используется как/в наиболее ограниченном режиме. Члены, которые не должны быть видны вне класса, должны быть определены как закрытые. Но это может быть нарушено с отражением, как мы видим. Но это не означает, что вы не должны использовать частные - или они небезопасны. Речь идет о том, что вы будете использовать вещи разумно или конструктивно (например, отражение).

+5
источник

Предполагая, что вы доверяете клиентскому программисту вашего API, еще один способ взглянуть на то, как "безопасно" для них использовать эти конкретные функции.

Ваши общедоступные функции должны обеспечивать четкий, хорошо документированный, редко меняющийся интерфейс в вашем коде. Ваши частные функции можно рассматривать как детали реализации и со временем могут меняться, поэтому их использование небезопасно.

Если клиент-программист делает все возможное, чтобы обойти эти абстракции, они заявляют, что знают, что они делают. Что еще более важно, они понимают, что они не поддерживаются и могут перестать работать с будущими версиями вашего кода.

+5
источник

private не для безопасности, он должен содержать код в чистоте и для предотвращения ошибок. Он позволяет пользователям модулировать код (и как он разработан), не беспокоясь обо всех деталях других модулей.

Как только вы отпустите свой код, люди могут понять, как он работает. Там нет способа "скрыть" логику, если вы в конечном итоге хотите, чтобы код работал на компьютере. Даже компиляция в двоичный файл представляет собой уровень обфускации.

Таким образом, вы не можете настроить свой API для выполнения особых действий, которые вы не хотите, чтобы другие могли звонить. В случае веб-API вы можете использовать методы, которые хотите контролировать на стороне сервера.

+5
источник

Посмотрите другие вопросы по меткам или Задайте вопрос