Является ли Reflection недостатком, поскольку частные переменные не могут быть ограничены?


14

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


2
Код с низким уровнем доверия не может использовать частное отражение (по крайней мере, на других сборках, я забыл детали). Код полного доверия может просто использовать указатели, чтобы обойти любые ограничения в процессе.
— CodesInChaos

55
Модификаторы закрытого доступа в основном существуют для того, чтобы сказать программистам: «не используйте это извне класса, и если вы действительно это делаете, не жалуйтесь, если следующая версия нарушает ваш код», а не как строго соблюдаемая функция безопасности.
— CodesInChaos


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

6
Разве это не вопрос конкретного языка? Отражение действует по-разному на разных языках. Мне интересно, если этот вопрос должен иметь тег для Java или что-то еще.
— Уэйн Конрад

Ответы:


54

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


33
Это не универсально верно. Цитируя Эрика Липперта , «Модификаторы доступа в CLR - это функции безопасности. Правила доступа полностью связаны с системами безопасности и безопасности типов». В C # Reflection доступен только для кода, работающего с полным доверием. Это не относится (и не может) применяться к злоумышленникам системы, работающим с кодом. Однако это относится к вредоносным плагинам.
— Брайан

5
@Brian Проблема, о которой упоминает Брайан, - это когда система позволяет стороннему коду запускаться без полного доверия. Примеры включают в себя «песочницы» браузера (например, очень ненавистный апплет), движок приложений Google и Azure . Для Azure было бы очень глупо разрешать ненадежному коду исследовать детали основных библиотек платформы.
— JimmyJames

3
@Brian Это не на 100% правильно - есть некоторые операции отражения, которые вы можете выполнять в частично доверенном коде; это просто не позволяет вам делать такие вещи, как доступ к закрытым полям.
— Луан

1
@ Брайан, пока кто-то не найдет уязвимость или социальную инженерию, которая позволяет им обойти ограничения. Нет смысла пытаться использовать их таким образом. Это не их основная цель.
— jpmc26

31

Чтобы процитировать Херб Саттер о правах доступа класса :

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


2
Там являются случаи , когда вам нужно песочнице ненадежного кода, но это задача сложная. Защита от ошибок (Мерфи) - гораздо более распространенный случай.
— Пол Дрейпер

#define private public(игнорируя, что это на самом деле неопределенное поведение) и вуаля у меня есть полный доступ извне к ограниченной части ваших классов.
— болов

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

@MarkJ. Замечание Херба Саттера о преднамеренном издевательстве со стороны разработчика, который первым написал класс, и, возможно, его товарищей по команде. Я не думаю, что есть способ предотвратить подобное злоупотребление языковыми функциями.
— Неманя Трифунович,

@bolov, что трюк зависит от языка, я думаю. Хотя препроцессоры C / C ++, вероятно, позволят вам избежать этого, все, что без них, вероятно, приведет к ошибке «нельзя использовать зарезервированные слова в #define».
— Дэн возится от Firelight

10

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


1
Другими словами, это способ обойти, вероятно, сломанный API - либо из-за неполных требований, либо из-за неполной реализации.
— Восстановить Монику

4

Вы еще больше ограничиваете доступность, поднимаясь на еще один уровень: среду исполнения.

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

Дополнительная информация о том, как сделать это в Java: Безопасность отражений


3

О каком отражении ты говоришь?

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

Если вас беспокоит инкапсуляция, простое решение состоит в том, чтобы просто не использовать систему отражения, которая не сохраняет ее.


3

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

В C # существуют модификаторы доступа, но они все еще являются лишь соглашением, которое обеспечивается компилятором, но все же соглашением. Это означает, что технически можно по-прежнему обращаться к закрытым переменным и изменять их, либо с помощью Reflection, либо напрямую изменяя память (как это делают тренеры игр ). Последствия точно такие же: если переменные вашего класса изменяются с помощью Reflection из другого класса или с помощью вмешательства в память другого приложения, и это что-то нарушает в вашем классе, это не ваша ошибка.

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


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