Чи є відображення недоліком, оскільки приватні змінні не можна обмежувати?


14

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


2
Код з низькою довірою не може використовувати приватне відображення (принаймні, не про інші збірки, я забув деталі). Повний код довіри може просто використовувати вказівники для обходу будь-яких обмежень у процесі.
CodesInChaos

55
Модифікатори приватного доступу в основному існують, щоб сказати програмістам "не використовувати це за межами класу, і якщо це дійсно так, не нарікайте, якщо наступна версія порушує ваш код" не як суворо застосовувана функція безпеки.
CodesInChaos


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

6
Це не специфічне для мови питання? Рефлексія діє по-різному в різних мовах. Мені цікаво, чи має це питання мати тег для Java чи щось інше.
Уейн Конрад

Відповіді:


54

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


33
Це не вірно. Цитуючи Еріка Ліпперта , "Модифікатори доступу в CLR - це функції безпеки. Правила доступу досконально пов'язані із системами безпеки та типу безпеки". У C # відображення доступне лише для коду, що працює під повним довірою. Це не (і не може) застосовуватись до шкідливих користувачів системи, які використовують код. Однак це стосується шкідливих плагінів.
Брайан

5
@Brian Якщо проблема, яку Брайан згадує, є актуальною, коли система дозволяє запускати сторонній код, не повністю довіряючи йому. Приклади включають пісочні скриньки браузера (наприклад, дуже ненависний аплет), двигун програми Google і Azure . Для Azure було б дуже глупо дозволити ненадійному коду досліджувати деталі основних бібліотек платформи.
JimmyJames

3
@Brian Це не на 100% правильно - є деякі операції з відображенням, які можна виконати в частково довіреному коді; це просто не дозволяє вам робити такі речі, як доступ до приватних полів.
Луань

1
@Brian, поки хтось не знайде вразливість або соціальну інженерію, яка дозволяє їм обійти обмеження. Немає сенсу намагатися їх використовувати таким чином. Це не їх головне призначення.
jpmc26

31

Щоб процитувати Herb Sutter про права доступу до класу :

"Проблема тут полягає в захисті від Мерфі проти захисту від Макіавеллі ... тобто захисту від випадкових зловживань (що мова робить дуже добре) проти захисту від навмисних зловживань (що фактично неможливо). Зрештою, якщо програміст хоче досить погано підривати систему, він знайде спосіб "


2
Там є випадки , коли вам потрібно пісочниці ненадійного коду, але це завдання складне. Захист від помилок (Мерфі) - набагато частіший випадок.
Пол Дрейпер

#define private public(ігноруючи, що це насправді не визначена поведінка) і вуаля, я маю повний доступ ззовні до обмеженої частини ваших занять.
болов

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

@MarkJ. Зауваження Герб Саттера стосується навмисних зловживань з боку розробника, який в першу чергу написав клас та, можливо, його товаришів по команді. Я не думаю, що існує спосіб запобігти такому зловживанню мовними особливостями.
Неманья Трифунович

@bolov, що трюк залежить від мови. Хоча препроцесори C / C ++, ймовірно, дозволять вам уникнути цього, все без них, ймовірно, дасть помилку "не може використовувати зарезервовані слова в #define".
Дан вигадує Firelight

10

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


1
Іншими словами, це спосіб обійти ймовірний порушений API - через неповні вимоги чи неповну реалізацію.
Відновіть Моніку

4

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

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

Більше інформації про це на Java: Reflection Security


3

Про яку рефлексію ви говорите?

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

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


3

У Python немає модифікаторів доступу. Конвенція полягає в тому, щоб підкреслити за допомогою підкреслення методи та змінні, до яких не очікується доступ за межами класу. Чи технічно це заважає вам отримати доступ до такого поля від стороннього класу? Зовсім не; але якщо ви це зробите, ви самостійно, і ви ризикуєте щось зламати, не маючи змоги звинуватити інший клас.

У C # модифікатори доступу існують, але вони все ще є лише умовою - такою, яку застосовує компілятор, але все ще конвенцією. Це означає, що в технічному відношенні ви все одно можете отримувати доступ та змінювати приватні змінні або через Reflection, або шляхом прямого втручання в пам'ять (як це роблять тренери з ігор ). Наслідок точно такий же: якщо змінні вашого класу змінюються через Reflection від іншого класу або через підробку пам’яті іншим додатком, і це щось порушує у вашому класі, це не ваша вина.

Зауважте, що це, очевидно, створює проблеми із безпекою, коли сторона може отримати доступ до ваших даних; те, що призводить до зашифрованих варіантів рядка та подібних структур даних. Але захист вашого коду від такого використання є більшою мірою пов’язаною з обмеженнями доступу до ОС та рівня коду і не має нічого спільного з Reflection як такою.


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