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.

user245930
fonte
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.

JacquesB
fonte
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 "

Nemanja Trifunovic
fonte
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.

Mason Wheeler
fonte
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

Comunidade
fonte
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.

Jörg W Mittag
fonte
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.

Arseni Mourzenko
fonte
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