O Reflection é uma desvantagem, pois as variáveis ​​privadas não podem ser restringidas?


14

O privatemodificador é usado para restringir o acesso fora da classe, mas usando a reflexão outras classes podem acessar métodos e campos privados. Então, eu estou querendo saber como podemos restringir a acessibilidade, se isso faz parte dos requisitos.


2
O código de baixa confiança não pode usar a reflexão privada (pelo menos não em outras montagens, esqueci os detalhes). O código de confiança completo pode simplesmente usar ponteiros para ignorar quaisquer restrições dentro do processo.
— CodesInChaos

55
Modificadores de acesso privado existem principalmente para dizer aos programadores "não usam isso de fora da classe e, se você realmente o fizer, não reclame se a próxima versão quebrar seu código", não como um recurso de segurança rigorosamente imposto.
— CodesInChaos


4
Os usuários também podem apenas corrigir seu código para fazer o que quiserem. Com uma exceção parcial para o DRM (que não é poderoso o suficiente para fornecer proteção duradoura), qualquer pessoa que tenha acesso ao seu aplicativo (binários ou código fonte) pode fazer qualquer coisa com ele.
— Brian

6
Esta não é uma pergunta específica do idioma? A reflexão opera de maneira diferente em diferentes idiomas. Gostaria de saber se esta pergunta deve ter uma tag para Java ou outra coisa.
— Wayne Conrad

Respostas:


54

O objetivo dos modificadores de acesso é informar aos desenvolvedores que escrevem código sobre qual é a interface pública de uma classe. Eles não são de forma alguma uma medida de segurança e não ocultam nem protegem literalmente nenhuma informação.


33
Isso não é universalmente verdade. Citando Eric Lippert , "Modificadores de acesso no CLR são recursos de segurança. As regras de acesso são totalmente conflitantes com os sistemas de segurança e de segurança de tipo". No C #, o Reflection está disponível apenas para código em execução sob total confiança. Isso não se aplica (e não pode) a usuários mal-intencionados do sistema que estão executando o código. No entanto, ele se aplica a plug-ins maliciosos.
— Brian

5
@ Brian Quando o problema mencionado por Brian é relevante, é quando um sistema permite que códigos de terceiros sejam executados sem confiar totalmente nele. Os exemplos incluem caixas de areia do navegador (por exemplo, o muito odiado applet), o google app engine e Azure . Seria realmente estúpido para o Azure permitir que código não confiável explore os detalhes das bibliotecas principais da plataforma.
— JimmyJames

3
@ Brian Isso não é 100% correto - existem algumas operações de reflexão que você pode fazer em código parcialmente confiável; apenas não permite que você faça coisas como acessar campos particulares.
— Luaan 13/09/16

1
@Brian Até que alguém encontre uma vulnerabilidade ou engenharia social que permita ignorar as restrições. Não faz sentido tentar usá-los dessa maneira. Esse não é o objetivo principal deles.
— Jpmc26

31

Para citar Herb Sutter sobre os direitos de acesso à classe :

"A questão aqui é proteger contra Murphy versus proteger contra Maquiavel ... ou seja, proteger contra uso indevido acidental (que a língua faz muito bem) vs. proteger contra abuso deliberado (que é efetivamente impossível). No final, se um programador quer o suficiente para subverter o sistema, ele encontrará uma maneira "


2
Não são momentos em que você precisa para código não confiável sandbox, mas isso é uma tarefa difícil. Proteger contra erros (Murphy) é o caso muito mais comum.
— Paul Draper

#define private public(ignorando que na verdade é comportamento indefinido) e pronto, tenho acesso total de fora para a parte restrita de suas aulas.
— bolov 14/09/16

A proteção contra abusos deliberados pode ser teoricamente impossível, mas é efetivamente possível, tornando o abuso suficientemente difícil para que ocorra muito raramente. É importante ser claro sobre isso. Caso contrário, o software não poderá ser utilizado em situações como dispositivos médicos críticos à vida.
— precisa saber é

@MarkJ. A observação de Herb Sutter é sobre abuso deliberado do desenvolvedor que escreveu a classe em primeiro lugar e talvez de seus companheiros de equipe. Não acho que exista uma maneira de impedir esse tipo de abuso por recursos de linguagem.
— Nemanja Trifunovic

@ Bolov que dublê é dependente da linguagem, eu acho. Enquanto os pré-processadores C / C ++ provavelmente permitiriam que você se desse bem, qualquer coisa sem eles provavelmente daria um erro "não é possível usar palavras reservadas em um #define".
— Dan is Fiddling por Firelight

10

Não, isso é realmente uma vantagem importante. Simplesmente porque algum desenvolvedor não considerou que alguém precisaria acessar algum estado interno não significa que nenhum caso de uso legítimo seja exibido. Nesses casos, o uso do Reflection para realizar cirurgia em um objeto pode ser o último recurso. Eu tive que usar essa técnica mais de uma vez.


1
Em outras palavras, é uma maneira de contornar uma provável API quebrada - seja devido a requisitos incompletos ou implementação incompleta.
— Restabeleça Monica

4

Você restringe ainda mais a acessibilidade subindo mais um nível: o ambiente de execução.

Nem todas as linguagens têm esse conceito, mas pelo menos com Java você pode usar um gerenciador de segurança que proíbe a disponibilização de campos privados. Você pode instalar manualmente o gerenciador de segurança em tempo de execução ou adicionar uma política de segurança em um arquivo jar que é selado para evitar modificações.

Mais informações sobre como fazer isso em Java: Reflection Security


3

De que reflexão você está falando?

Em muitos sistemas de reflexão, contornar o encapsulamento é um recurso explícito que seu código precisa obter e não possui por padrão.

Se você está preocupado com o encapsulamento, a solução simples é simplesmente não usar um sistema de reflexão que não o preserve.


3

No Python, não há modificadores de acesso. A convenção é prefixar com um sublinhado os métodos e variáveis ​​que não se espera que sejam acessados ​​de fora da classe. Tecnicamente, isso impede que você acesse esse campo de uma classe de terceiros? De modo nenhum; mas, se o fizer, estará por sua conta e correrá o risco de quebrar alguma coisa, sem poder culpar a outra classe.

No C #, existem modificadores de acesso, mas eles ainda são apenas uma convenção - que é imposta por um compilador, mas ainda é uma convenção. Isso significa que, tecnicamente, ainda é possível acessar e alterar variáveis ​​privadas, através do Reflection ou violando diretamente a memória (como fazem os treinadores de jogos ). A conseqüência é exatamente a mesma: se as variáveis ​​da sua classe forem alteradas através do Reflection de outra classe, ou através da violação de memória de outro aplicativo, e isso interromper algo na sua classe, a culpa não é sua.

Observe que, obviamente, isso cria problemas de segurança nos quais terceiros podem acessar seus dados; algo que leva a variantes criptografadas de uma string e estruturas de dados semelhantes. Mas proteger seu código contra esse uso está relacionado a restrições de acesso ao sistema operacional e ao nível do código , e não tem nada a ver com o Reflection em si.


2
Observe que, em C #, apenas códigos totalmente confiáveis ​​podem refletir membros particulares. Escrever diretamente na memória do processo ainda funciona, mas é mais difícil do que no código nativo.
— Luaan 13/09/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.