Reflection è uno svantaggio in quanto le variabili private non possono essere limitate?


14

Il privatemodificatore viene utilizzato per limitare l'accesso al di fuori della classe, ma utilizzando la riflessione altre classi possono accedere a metodi e campi privati. Quindi mi chiedo come possiamo limitare l'accessibilità se fa parte dei requisiti.


2
Il codice di attendibilità basso non può utilizzare la riflessione privata (almeno non su altri assembly, ho dimenticato i dettagli). Il codice di affidabilità completo può semplicemente utilizzare i puntatori per aggirare eventuali restrizioni all'interno del processo.
Codici InCos

55
I modificatori di accesso privato esistono principalmente per dire ai programmatori "non utilizzarli al di fuori della classe e, se lo fai davvero, non lamentarti se la versione successiva rompe il tuo codice" non come una funzionalità di sicurezza rigorosamente applicata.
Codici InCos


4
Gli utenti possono anche semplicemente patchare il codice per fare quello che vogliono. Con un'eccezione parziale per DRM (che non è abbastanza potente da fornire una protezione duratura), chiunque abbia accesso alla tua applicazione (binari o codice sorgente) può farci qualsiasi cosa.
Brian,

6
Non è una domanda specifica della lingua? Reflection opera in modo diverso in diverse lingue. Mi chiedo se questa domanda dovrebbe avere un tag per Java o qualcos'altro.
Wayne Conrad,

Risposte:


54

Lo scopo dei modificatori di accesso è informare gli sviluppatori che scrivono codice su quale sia l'interfaccia pubblica di una classe. Non sono in alcun modo una misura di sicurezza e non nascondono o proteggono letteralmente alcuna informazione.


33
Questo non è universalmente vero. Citando Eric Lippert , "I modificatori di accesso nel CLR sono caratteristiche di sicurezza. Le regole di accesso sono completamente integrate con i sistemi di sicurezza e di sicurezza dei tipi." In C #, Reflection è disponibile solo per il codice eseguito in piena fiducia. Ciò non si applica (e non può) agli utenti malintenzionati del sistema che eseguono il codice. Tuttavia, si applica ai plug-in dannosi.
Brian,

5
@Brian Dove il problema citato da Brian è rilevante quando un sistema consente l'esecuzione di codice di terze parti senza fidarsi completamente di esso. Gli esempi includono sandbox del browser (ad esempio l'applet molto odiato), il motore di app di Google e Azure . Sarebbe davvero stupido per Azure consentire al codice non attendibile di esplorare i dettagli delle librerie principali della piattaforma.
JimmyJames,

3
@Brian Non è corretto al 100% - ci sono alcune operazioni di riflessione che puoi fare in codice parzialmente attendibile; semplicemente non ti consente di fare cose come accedere ai campi privati.
Luaan,

1
@Brian Fino a quando qualcuno non trova una vulnerabilità o un social engineering che gli consente di aggirare le restrizioni. Non ha senso cercare di usarli in quel modo. Questo non è il loro scopo principale.
jpmc26,

31

Per citare Herb Sutter sui diritti di accesso alla classe :

"Il problema qui è quello di proteggere contro Murphy contro proteggere contro Machiavelli ... vale a dire, proteggere contro l'uso improprio accidentale (che la lingua fa molto bene) rispetto a proteggere contro l'abuso deliberato (che è effettivamente impossibile). Alla fine, se un programmatore vuole abbastanza da sovvertire il sistema, troverà un modo "


2
Ci sono momenti in cui è necessario eseguire il sandbox del codice non attendibile, ma è un'attività scoraggiante. La protezione dagli errori (Murphy) è il caso molto più comune.
Paul Draper,

#define private public(ignorando che in realtà è Comportamento indefinito) e voilà ho pieno accesso dall'esterno alla parte riservata delle tue lezioni.
Bolov,

La protezione contro l'abuso deliberato può essere teoricamente impossibile, ma è effettivamente possibile, rendendo l'abuso sufficientemente difficile da accadere molto raramente. È importante essere chiari al riguardo. Altrimenti il ​​software non potrebbe essere utilizzato affatto in situazioni come dispositivi medici critici per la vita.
MarkJ,

@MarkJ. L'osservazione di Herb Sutter riguarda l'abuso deliberato da parte dello sviluppatore che ha scritto la classe in primo luogo e forse i suoi compagni di squadra. Non penso che ci sia un modo per prevenire questo tipo di abuso con le funzionalità del linguaggio.
Nemanja Trifunovic,

@bolov che la prodezza dipende dalla lingua penso. Mentre i preprocessori C / C ++ probabilmente ti permetterebbero di cavartela, qualsiasi cosa senza di loro darebbe probabilmente un errore "impossibile usare parole riservate in un #define".
Dan è Fiddling di Firelight il

10

No, questo è in realtà un vantaggio importante. Il semplice fatto che alcuni sviluppatori non abbiano ritenuto che qualcuno avrebbe avuto bisogno di accedere a una parte dello stato interno non significa che nessun caso d'uso legittimo verrà mai presentato. In questi casi, l'utilizzo di Reflection per eseguire un intervento chirurgico su un oggetto può essere l'ultima risorsa. Ho dovuto usare questa tecnica più di una volta.


1
In altre parole, è un modo per aggirare un'API probabilmente rotta, a causa di requisiti incompleti o implementazione incompleta.
Ripristina Monica il

4

Limiti ulteriormente l'accessibilità salendo di un livello in più: l'ambiente di esecuzione.

Non tutte le lingue hanno questo concetto, ma almeno con Java puoi usare un gestore della sicurezza che vieta di rendere accessibili i campi privati. È possibile installare manualmente il gestore della sicurezza in fase di esecuzione o aggiungere una politica di sicurezza in un file jar che viene quindi sigillato per impedire modifiche.

Maggiori informazioni su come farlo in Java: Reflection Security


3

Di quale riflessione stai parlando?

In molti sistemi di riflessione, aggirare l'incapsulamento è una capacità esplicita che il codice deve ottenere e che non ha per impostazione predefinita.

Se sei preoccupato per l'incapsulamento, la soluzione semplice è semplicemente non utilizzare un sistema di riflessione che non lo preservi.


3

In Python non ci sono modificatori di accesso. La convenzione prevede il prefisso con un carattere di sottolineatura dei metodi e delle variabili a cui non si prevede di accedere dall'esterno della classe. Tecnicamente ti impedisce di accedere a tale campo da una classe di terze parti? Affatto; ma se lo fai, sei da solo e corri il rischio di rompere qualcosa, senza poter incolpare l'altra classe.

In C #, esistono modificatori di accesso, ma sono ancora solo una convenzione, quella che viene applicata da un compilatore, ma è comunque una convenzione. Ciò significa che tecnicamente, è ancora possibile accedere e modificare le variabili private, tramite Reflection o manomettendo direttamente la memoria (come i game trainer ). La conseguenza è esattamente la stessa: se le variabili della tua classe vengono modificate tramite Reflection da un'altra classe o tramite manomissione della memoria da un'altra applicazione e si rompe qualcosa nella tua classe, non è colpa tua.

Nota che questo, ovviamente, crea problemi di sicurezza in cui una terza parte può accedere ai tuoi dati; qualcosa che porta a varianti crittografate di una stringa e strutture di dati simili. Ma proteggere il tuo codice da tale utilizzo è più legato al sistema operativo e alle restrizioni di accesso a livello di codice e non ha nulla a che fare con Reflection in sé.


2
Si noti che in C #, solo il codice completamente attendibile può riflettere i membri privati. Scrivere direttamente nella memoria di processo funziona ancora, ma è più difficile che nel codice nativo.
Luaan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.