В 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, чтобы прояснить свой вопрос.
Советы по выбору уровня доступа:
Если ваш класс используют другие программисты, вы хотите убедиться, что ошибки из-за неправильного использования не возникнут. В этом вам могут помочь уровни доступа. Используйте самый ограничительный уровень доступа, который имеет смысл для конкретного участника. Используйте приватное, если у вас нет веской причины не делать этого.
источник
getDeclaredMethods
возвращает имена, которые выглядят как мусор.Ответы:
Это зависит от того, что вы подразумеваете под словом «безопасный». Если вы работаете с менеджером безопасности, который допускает подобные вещи, то да, вы можете делать с отражением всевозможные неприятные вещи. Но тогда в такой среде библиотеку, вероятно, можно просто изменить, чтобы сделать метод общедоступным.
В такой среде контроль доступа фактически является «рекомендательным» - вы действительно доверяете коду, чтобы он работал хорошо. Если вы не доверяете выполняемому коду, вам следует использовать более строгий менеджер безопасности.
источник
check*
основном выдает исключения для соответствующих вызовов.Модификаторы доступа не имеют ничего общего с безопасностью. Фактически, вы можете и должны смотреть на модификаторы доступа как на обратную сторону безопасности - они предназначены не для защиты ваших данных или алгоритмов, а для защиты людей от необходимости знать о ваших данных и алгоритмах. Вот почему модификатор по умолчанию - package - если они работают с пакетом, им, вероятно, уже нужно знать.
Вместе со знанием данных и методов вашего кода приходит ответственность знать, когда и как их использовать. Вы не ставите приватный в свой метод inIt, чтобы кто-то не узнал об этом, вы делаете это потому, что (а) они не узнают, что вы вызываете это только после foo и только если bar = 3.1415 и (b) потому что им нечего об этом знать.
Modifers доступа можно суммировать в простой фразе «TMI, чувак, я так не нужно знать , что».
источник
Говоря «безопасно», вы защищаете себя или других разработчиков, которые используют ваш API, чтобы не навредить объекту, вызывая ваш частный метод. Но если вам или им действительно нужно вызвать этот метод, они могут сделать это с помощью Reflection.
источник
Вопрос в том, от кого вы пытаетесь его спасти . На мой взгляд, такой клиент вашего кода здесь в убытке.
Любой фрагмент кода (написанный вами или другими), который пытается получить доступ к
private
члену вышеуказанного класса, по сути, роет себе могилу.private
члены не являются частью общедоступного API и могут быть изменены без предварительного уведомления. Если клиент использует один из таких закрытых членов описанным выше способом, он сломается, если обновится до более новой версии API, в которой частный член был изменен.источник
С легкостью приходит ответственность. Есть вещи, которые нельзя делать, и есть вещи, которые можно делать, но делать не следует .
Приватный модификатор предоставляется / используется наиболее ограниченным образом. Члены, которые не должны быть видимы вне класса, должны быть определены как частные. Но, как мы видим, это можно сломать с помощью Reflection. Но это не значит, что вы не должны использовать приватные - или они небезопасны. Речь идет о том, что вы должны использовать вещи разумно или конструктивно (например, размышления).
источник
Предполагая, что вы доверяете клиентскому программисту своего API, другой способ взглянуть на то, насколько «безопасно» для них использовать эти конкретные функции.
Ваши общедоступные функции должны обеспечивать четкий, хорошо документированный, редко меняющийся интерфейс в вашем коде. Ваши частные функции можно рассматривать как деталь реализации и со временем они могут изменяться, поэтому использовать их напрямую небезопасно.
Если клиентский программист изо всех сил пытается обойти эти абстракции, он в некотором смысле заявляет, что знает, что делает. Что еще более важно, они понимают, что он не поддерживается и может перестать работать с будущими версиями вашего кода.
источник
private
не для безопасности, а для того, чтобы код был чистым и не допускал ошибок. Это позволяет пользователям модулировать код (и способы его разработки), не беспокоясь обо всех деталях других модулей.Как только вы выпустите свой код, люди смогут понять, как он работает. Невозможно «скрыть» логику, если вы хотите, чтобы код запускался на компьютере. Даже компиляция в двоичную форму - это просто уровень запутывания.
Таким образом, вы не можете настроить свой API для выполнения особых действий, которые вы не хотите, чтобы другие могли вызывать. В случае веб-API вы можете поместить методы, которыми хотите управлять, на стороне сервера.
источник