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

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

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

public class ProtectedPrivacy{

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

}  

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

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, чтобы прояснить свой вопрос.

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

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


person Ruchira Gayan Ranaweera    schedule 08.11.2013    source источник
comment
Использование обфускатора может помочь, потому что getDeclaredMethods будет возвращать имена, которые выглядят как мусор.   -  person Sergey Kalinichenko    schedule 08.11.2013
comment
Частный, защищенный общедоступный и т. Д. Не для безопасности, а для того, чтобы люди не совершали ошибок из лучших побуждений. Не используйте его в качестве меры безопасности   -  person Richard Tingle    schedule 08.11.2013
comment
Код Java в любом случае декомпилируется. «Злоумышленник» может просто загрузить декомпилятор Java и прочитать ваш код или изменить «частное» на «общедоступное».   -  person 11684    schedule 08.11.2013
comment
Чтобы уточнить, что прокомментировал @RichardTingle (кстати, +1). Существует большое и важное различие между безопасностью и безопасностью. В последнем случае проблема решается с помощью модификаторов доступа; чтобы ничего не сломать случайно   -  person user    schedule 08.11.2013
comment
Все это довольно понятно программистам, где модификаторов доступа не существует, как в Python. В этих языках частные и общедоступные просто различаются по соглашению в именах (в питоне все, что начинается с одного подчеркивания, должно считаться частным). Это делает очевидным тот факт, что пометка чего-либо как закрытого не добавляет безопасности, но это всего лишь простой способ указать, что люди должны использовать в вашем API. У меня есть сомнения, что проверка компилятором на эти вещи вообще поможет, поскольку чертовски легко следовать соглашению без внешней помощи.   -  person Bakuriu    schedule 09.11.2013
comment
Системы внедрения зависимостей и библиотеки ORM часто используют отражение, чтобы обойти private. Затем модификатор private становится Программистам не нужно и не следует знать об этом. Системные службы могут, но программисты должны только настраивать их для взаимодействия с ними. Предположим, вы пытаетесь использовать программирование без получения, используя Name.appendFullName(Appendable) вместо Name.getGivenName() и Name.getSurName(). Вы по-прежнему можете использовать Hibernate для получения Name объектов из базы данных.   -  person Eric Jablow    schedule 13.11.2013
comment
может быть ссылка поможет вам stackoverflow.com/questions/7566626/   -  person Nikesh Pathak    schedule 13.11.2013
comment
Ваш вопрос действительно звучит так: как мне запретить отражению доступ к моим личным частям? Вы можете подумать о том, чтобы перефразировать его, если у вас нет другого намерения.   -  person Glenn Teitelbaum    schedule 15.11.2013


Ответы (7)


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

Контроль доступа фактически является «рекомендательным» в такой среде — вы фактически доверяете коду, чтобы он хорошо работал. Если вы не доверяете коду, который используете, вам следует использовать менеджер безопасности с более строгими ограничениями.

person Jon Skeet    schedule 08.11.2013
comment
Касательно, я знаю, но не могли бы вы немного пояснить, каким в этом смысле может быть более ограничительный менеджер? - person Gray; 08.11.2013
comment
@Gray: экземпляр SecurityManager, который в основном выдает исключения для соответствующих вызовов check*. - person Jon Skeet; 08.11.2013

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

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

Модификаторы доступа можно охарактеризовать простой фразой «TMI, чувак, мне поэтому не нужно было этого знать».

person jmoreno    schedule 08.11.2013
comment
Отличный ответ, но мне нужно было погуглить, чтобы узнать, что TMI означает слишком много информации. Думаю, мне нужно проводить больше времени в долине :-) - person mikelong; 15.11.2013

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

person Arsen Alexanyan    schedule 08.11.2013

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

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

person Community    schedule 08.11.2013

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

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

person Raúl    schedule 08.11.2013

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

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

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

person robbie_c    schedule 08.11.2013

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

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

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

person Manishearth    schedule 09.11.2013