Pretese
Aggiornamento: novembre 2007
È possibile utilizzare le chiamate di pretese di protezione in modo dichiarativo o imperativo per specificare le autorizzazioni necessarie ai chiamanti diretti o indiretti per accedere alla libreria. I chiamanti diretti chiamano in modo esplicito metodi statici o di istanza della libreria, mentre i chiamanti indiretti chiamano metodi statici o di istanza di una libreria che chiama a sua volta la libreria. Quando si utilizza una pretesa, qualsiasi applicazione che includa il codice verrà eseguita solo se i chiamanti diretti e indiretti dispongono delle autorizzazioni specificate nella pretesa stessa. Le pretese sono di particolare utilità nelle situazioni in cui la libreria di classi utilizza risorse protette di cui si desidera impedire l'accesso da parte di codice non attendibile. Per inserire le pretese nel codice, è possibile utilizzare sia la sintassi imperativa che la sintassi dichiarativa.
Si noti che, poiché a molte classi di .NET Framework sono già associate delle pretese, non è sempre necessario creare un'ulteriore pretesa ogni volta che si utilizza una classe che accede a una risorsa protetta. La classe StreamWriter ad esempio genera automaticamente una pretesa di protezione di FileIOPermission ogni volta che viene aperta. Se si genera una pretesa di FileIOPermission quando si utilizza la classe StreamWriter, l'analisi dello stack sarà ridondante e inefficiente. È consigliabile utilizzare le pretese per proteggere risorse personalizzate che richiedono autorizzazioni personalizzate.
Le pretese possono essere dichiarative o imperative.
Analisi dello stack
Le pretese implementano la protezione eseguendo la cosiddetta analisi dello stack, mediante la quale viene verificata la disponibilità dell'autorizzazione specificata per ogni funzione chiamante (o stack frame) nello stack di chiamate corrente. Quando viene attivata una pretesa si verifica quanto segue.
L'analisi dello stack inizia in corrispondenza dello stack frame del chiamante e non dello stack corrente relativo alla pretesa. Ad esempio, se il metodo A chiama il metodo B e quest'ultimo ha una pretesa, l'analisi dello stack inizia in corrispondenza dello stack frame del metodo A. Il metodo B non viene mai valutato nell'ambito dell'analisi dello stack.
L'analisi prosegue attraverso lo stack di chiamate finché non viene raggiunto il punto di ingresso del programma (in genere il metodo Main) oppure finché non viene trovato un modificatore di analisi dello stack, ad esempio un'asserzione. Per informazioni sui modificatori di analisi dello stack, vedere Override dei controlli di protezione.
Quando una pretesa e un modificatore di analisi dello stack, ad esempio un'asserzione, relativi alla stessa autorizzazione appaiono sullo stesso stack frame, è la pretesa ad avere priorità.
La sintassi dichiarativa e quella imperativa non presentano differenze nel comportamento.
Si noti che una pretesa sul punto di ingresso del programma non viene mai valutata perché l'analisi dello stack inizia sempre in corrispondenza dello stack frame del chiamante, ma in questo caso non è presente il frame chiamante da valutare. Di conseguenza, le pretese su un punto di ingresso del programma hanno sempre esito positivo.
Pretese dichiarative
Mediante le pretese dichiarative si inseriscono informazioni nei metadati del codice con l'impiego di attributi. È possibile utilizzare la sintassi dichiarativa per specificare una pretesa al livello di classe o al livello di metodo del codice.
Se si specifica un controllo di protezione dichiarativo a livello di classe, tale controllo avrà effetto su tutti i membri della classe. Se invece si specifica un controllo di protezione dichiarativo a livello di membro, tale controllo avrà effetto solo sul membro ed effettuerà l'override dell'autorizzazione specificata a livello di classe, se ne esiste una. Si supponga, ad esempio, di avere specificato a livello di classe che è necessaria un'autorizzazione A e di avere indicato per il metodo 1 della classe che è necessaria un'autorizzazione B. Quando viene chiamato il metodo 1, il controllo di protezione verificherà solo la presenza dell'autorizzazione B, ma per gli altri metodi della classe continuerà a essere necessaria l'autorizzazione A.
Nell'esempio seguente viene specificata una pretesa dichiarativa di un'autorizzazione personalizzata denominata CustomPermission su tutti i chiamanti del metodo ReadData. Si tratta di un'autorizzazione personalizzata fittizia, che non esiste realmente in .NET Framework. L'autorizzazione personalizzata dispone di un CustomPermissionAttribute definito separatamente, che consente l'effettuazione della pretesa. In questo caso, assume un flag SecurityAction.Demand per specificare il tipo di pretesa che verrà specificata tramite l'attributo.
<CustomPermissionAttribute(SecurityAction.Demand, Unrestricted := True)>Public Shared Function ReadData() As String
'Read from a custom resource.
End Function
[CustomPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
public static string ReadData()
{
//Read from a custom resource.
}
Pretese imperative
Le pretese imperative vengono inserite a livello di metodo nel codice mediante la creazione di una nuova istanza di un oggetto autorizzazione e chiamando il metodo Demand dell'oggetto stesso. Non è possibile utilizzare la sintassi imperativa per specificare pretese a livello di classe.
La pretesa imperativa specificata nel codice consente di proteggere efficacemente tutto il codice che rimane nel metodo in cui viene chiamato il metodo Demand. Il controllo di sicurezza viene eseguito al momento dell'esecuzione di Demand. Se il controllo ha esito negativo, viene generato un oggetto SecurityException e il codice rimanente all'interno del metodo o del membro non verrà mai eseguito, a meno che l'oggetto SecurityException non venga rilevato e gestito.
Nell'esempio riportato di seguito la sintassi imperativa viene utilizzata per specificare su tutti i chiamanti una pretesa dell'autorizzazione personalizzata CustomPermission. Viene creata una nuova istanza della classe CustomPermission che passa il flag PermissionState.Unrestricted al costruttore. Viene quindi chiamato il metodo Demand.
Public Shared Sub ReadData()
Dim MyPermission As New CustomPermission(PermissionState.Unrestricted)
MyPermission.Demand()
'Read from a custom resource.
End Sub
public static void ReadData()
{
CustomPermission MyPermission = new CustomPermission(PermissionState.Unrestricted);
MyPermission.Demand();
//Read from a custom resource.
}
Nota: |
---|
Il comportamento dell'ottimizzazione per le pretese varia in base alla piattaforma, a 64 o a 32 bit. Sulle piattaforme a 64 bit una pretesa non verifica il set di autorizzazioni dell'assembly che la contiene quando non sono presenti altri assembly chiamanti. Tuttavia, questa ottimizzazione non determina un'elevazione di privilegi perché viene comunque eseguita un'analisi dello stack quando sono presenti assembly chiamanti. Sulle piattaforme a 32 bit una pretesa verifica il set di autorizzazioni dell'assembly che la contiene e di tutti gli assembly chiamanti. |
Vedere anche
Concetti
Creazione di autorizzazioni personalizzate di accesso al codice
Aggiunta del supporto della protezione dichiarativa
Scrittura di librerie di classi protette