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

14

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

user245930
источник
2
Код с низким уровнем доверия не может использовать частное отражение (по крайней мере, на других сборках, я забыл детали). Код полного доверия может просто использовать указатели, чтобы обойти любые ограничения в процессе.
CodesInChaos
55
Модификаторы закрытого доступа в основном существуют для того, чтобы сказать программистам: «не используйте это извне класса, и если вы действительно это делаете, не жалуйтесь, если следующая версия нарушает ваш код», а не как строго соблюдаемая функция безопасности.
CodesInChaos
4
Пользователи также могут просто пропатчить ваш код, чтобы делать что угодно. За частичным исключением для DRM (которое недостаточно мощное, чтобы обеспечить длительную защиту), любой, кто имеет доступ к вашему приложению (двоичные файлы или исходный код), может делать с ним что угодно.
Брайан
6
Разве это не вопрос конкретного языка? Отражение действует по-разному на разных языках. Мне интересно, если этот вопрос должен иметь тег для Java или что-то еще.
Уэйн Конрад

Ответы:

54

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

JacquesB
источник
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 # только полностью доверенный код может отражать закрытые члены. Запись непосредственно в память процесса все еще работает, но сложнее, чем в собственном коде.
Луан