Чи приватні методи насправді безпечні?


92

У 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 .

Поради щодо вибору рівня доступу:

Якщо інші програмісти використовують ваш клас, ви хочете переконатися, що помилок від неправильного використання не може бути. У цьому вам можуть допомогти рівні доступу. Використовуйте найбільш обмежений рівень доступу, який має сенс для певного учасника. Використовуйте приватне, якщо у вас немає вагомих причин цього не робити.


1
Використання обфускатора може допомогти, оскільки getDeclaredMethodsповерне імена, схожі на сміття.
dasblinkenlight

213
Приватне, захищене державне тощо - це не для безпеки, а для того, щоб уникнути помилкових людей. Не використовуйте його як захід безпеки
Річард Тінгл

20
Код Java у будь-якому випадку можна розкласти. "Зловмисник" міг просто завантажити декомпілятор Java і прочитати ваш код, або змінити "приватний" на "загальнодоступний".
11684

7
Щоб детальніше розказати про те, що коментував @RichardTingle (+1 btw). Існує велика і важлива різниця між безпекою та безпекою. Де останнє - проблема, пом’якшена за допомогою модифікаторів доступу; щоб не зламати речі випадково
користувач

3
Все це досить зрозуміло програмістам, де модифікатори доступу не існують, як у Python. У цих мовах приватний / загальнодоступний просто відрізняються узгодженням в назвах (у python все, що починається з одного підкреслення, слід вважати приватним). Це робить цілком зрозумілим, що позначення чогось як "приватного" не додає жодної безпеки, але це лише простий спосіб сказати, що люди повинні використовувати у вашому API. Я сумніваюся, що перевірка компілятора на ці речі взагалі допомагає, оскільки дотримуватися конвенції без «зовнішньої» допомоги дуже просто.
Бакуріу

Відповіді:


95

Це залежить від того, що ви маєте на увазі під словом «безпечний». Якщо ви працюєте з менеджером з безпеки, який дозволяє подібні речі, то так, ви можете робити всілякі неприємні речі з відображенням. Але тоді в такому середовищі бібліотеку, можливо, можна просто модифікувати, щоб зробити метод загальнодоступним.

Контроль доступу є ефективною "порадою" в такому середовищі - ви фактично довіряєте коду, щоб він добре грав. Якщо ви не довіряєте коду, який ви використовуєте, вам слід використовувати більш обмежений менеджер безпеки.


3
Тангенціально, я знаю, але чи могли б Ви трохи детальніше розказати, яким би був більш обмежувальний менеджер у цьому сенсі?
Сірий

12
@Gray: Екземпляр SecurityManager, який створює виключення для відповідних check*викликів.
Джон Скіт,

40

Модифікатори доступу не мають нічого спільного з безпекою. Насправді ви можете і повинні розглядати модифікатори доступу як зворотний бік безпеки - це не захист ваших даних або алгоритмів, це захист людей від вимоги знати про ваші дані та алгоритми. Ось чому модифікатором за замовчуванням є пакет - якщо вони працюють над пакетом, їм, мабуть, уже потрібно знати.

Поряд із знанням даних та методів вашого коду приходить відповідальність знати, коли і як ними користуватися. Ви не ставите приватне у своєму методі inIt, щоб хтось не дізнався про це, ви робите це, тому що (а) вони не знатимуть, що ви дзвоните це лише після foo і лише якщо bar = 3.1415 та (b) бо їм не годиться знати про це.

Модифікатори доступу можна резюмувати простою фразою "TMI, чувак, мені так не потрібно було цього знати".


3
Чудова відповідь, але мені потрібно було загуглити, щоб з’ясувати, що TMI означає занадто багато інформації. Думаю, мені потрібно проводити більше часу в долині :-)
mikelong

7

Вимовляючи "безпечно", ви захищаєте себе або інших розробників, які використовують ваш API, щоб не завдати шкоди об'єкту, викликаючи ваш приватний метод. Але якщо вам або їм дійсно потрібно зателефонувати за цим методом, вони можуть це зробити за допомогою Reflection.


6

Питання в тому, від кого ви намагаєтесь його врятувати . На мою думку, такий клієнт вашого коду тут втрачає.

Будь-який фрагмент коду (написаний вами чи іншими), який намагається отримати доступ до privateчлена вищевказаного класу, по суті риє власну могилу. privateучасники не входять до загальнодоступного API і можуть змінюватися без попередження. Якщо клієнт випадково споживає одного з таких приватних членів способом, наведеним вище, він зламається, якщо оновиться до нової версії API, в якій приватний член був змінений.


5

Завдяки об'єкту приходить відповідальність. Є речі, яких ти не можеш зробити, і речі, які ти можеш робити, але ти не повинен робити.

Приватний модифікатор надається / використовується як / у найбільш обмеженому порядку. Члени, які не повинні бути видимими поза класом, визначаються як приватні. Але це можна зламати за допомогою Рефлексії, як ми бачимо. Але це не означає, що ви не повинні користуватися приватними - або вони небезпечні. Йдеться про те, щоб ви використовували речі розсудливо чи конструктивно (наприклад, роздуми).


5

Якщо припустити, що ви довіряєте програмісту-клієнту вашого API, інший спосіб поглянути на те, наскільки безпечним для них є використання цих конкретних функцій.

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

Якщо клієнт-програміст намагається обійти ці абстракції, він таким чином заявляє, що знає, що робить. Що ще важливіше, вони розуміють, що він не підтримується, і можуть перестати працювати з майбутніми версіями вашого коду.


5

privateне для безпеки, а для підтримки чистоти коду та запобігання помилкам. Це дозволяє користувачам модулювати код (і як він розробляється), не турбуючись про всі деталі інших модулів

Щойно ви випустите свій код, люди зможуть зрозуміти, як він працює. Немає можливості "приховати" логіку, якщо з часом ви хочете, щоб код працював на комп'ютері. Навіть компіляція в двійковий файл - це лише рівень затуманення.

Отже, ви не можете налаштувати свій API на особливі дії, які ви не хочете, щоб інші могли телефонувати. У разі веб-API ви можете перенести методи, якими ви хочете керувати, на сторону сервера.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.