Condividi tramite


Utilizzo del metodo Assert

Aggiornamento: novembre 2007

Il metodo Assert può essere chiamato nelle classi di autorizzazione di accesso al codice e nella classe PermissionSet. È possibile utilizzare Assert per consentire al codice e ai chiamanti downstream di eseguire le operazioni per cui il codice è autorizzato, anche qualora i chiamanti a monte del codice siano privi di tale autorizzazione. Un'asserzione di sicurezza consente di modificare il normale processo eseguito dal runtime durante un controllo di sicurezza. Mediante l'asserzione di un'autorizzazione si impone al sistema di sicurezza di non eseguire il controllo dei chiamanti del codice relativamente all'autorizzazione oggetto dell'asserzione.

Attenzione:

Utilizzare con cautela le asserzioni, in quanto possono introdurre vulnerabilità nel sistema di sicurezza e compromettere il meccanismo runtime per l'applicazione delle restrizioni di sicurezza.

Le asserzioni risultano utili nelle situazioni in cui una libreria chiama codice non gestito o effettua una chiamata che richiede un'autorizzazione non direttamente correlata all'utilizzo previsto della libreria. In tutto il codice gestito che consente di chiamare codice non gestito, ad esempio, devono essere specificati una SecurityPermission e un flag UnmanagedCode. Per impostazione predefinita, il codice che non ha origine nel computer locale, ad esempio quello scaricato dalla rete Intranet locale, non otterrà questa autorizzazione. Perché il codice scaricato dalla rete Intranet locale consente di chiamare una libreria in cui si utilizza codice non gestito, sarà quindi necessario eseguire un'asserzione dell'autorizzazione a livello di libreria. È inoltre possibile che alcune librerie effettuino chiamate non visualizzate ai chiamanti e che richiedano autorizzazioni specifiche.

Le asserzioni possono anche essere utilizzate nelle situazioni in cui il codice accede a una risorsa in modo completamente invisibile ai chiamanti. Si supponga, ad esempio, che la libreria acquisisca informazioni da un database, ma durante l'elaborazione legga ulteriori informazioni nel Registro di sistema del computer. Dal momento che gli sviluppatori che utilizzano la libreria non hanno accesso al codice sorgente, non possono in alcun modo sapere che per potere utilizzare il codice è necessaria l'autorizzazione RegistryPermission. In questo caso, se si stabilisce che non è ragionevole o necessario imporre che i chiamanti del codice dispongano di un'autorizzazione per accedere al Registro di sistema, è possibile effettuare un'asserzione di autorizzazione in relazione alla lettura del Registro di sistema. È consigliabile, in questa situazione, che la libreria effettui l'asserzione dell'autorizzazione in modo che i chiamanti privi di RegistryPermission possano comunque utilizzarla.

L'asserzione influisce sull'analisi dello stack solo se l'autorizzazione che ne è oggetto e l'autorizzazione richiesta da un chiamante downstream sono dello stesso tipo e se l'autorizzazione richiesta è un sottoinsieme dell'autorizzazione oggetto dell'asserzione. Se, ad esempio, si effettua un'asserzione di FileIOPermission per la lettura di tutti i file contenuti nell'unità C e viene generata una richiesta downstream di FileIOPermission per la lettura dei file contenuti nella cartella C:\Temp, l'asserzione può influire sull'analisi dello stack. Se invece la richiesta di FileIOPermission riguarda la scrittura sull'unità C, l'asserzione non avrà effetto.

Perché sia possibile effettuare asserzioni, è necessario che il codice disponga sia dell'autorizzazione oggetto dell'asserzione sia dell'autorizzazione SecurityPermission che rappresenta il diritto di effettuare asserzioni. Benché sia possibile effettuare l'asserzione di un'autorizzazione non concessa al codice, tale operazione non avrebbe alcun significato, poiché il controllo di sicurezza avrebbe esito negativo ancor prima che l'asserzione ne potesse garantire la riuscita.

Nell'illustrazione che segue vengono mostrate le fasi dell'utilizzo del metodo Assert. Si supponga che le seguenti affermazioni siano valide per gli assembly A, B, C, E e F e per le due autorizzazioni P1 e P1A:

  • P1A rappresenta il diritto di leggere i file TXT contenuti nell'unità C.

  • P1 rappresenta il diritto di leggere tutti i file contenuti nell'unità C.

  • P1A e P1 sono entrambi tipi FileIOPermissions e P1A è un sottoinsieme di P1.

  • Agli assembly E ed F è stata concessa l'autorizzazione P1A.

  • All'assembly C è stata concessa l'autorizzazione P1.

  • Agli assembly A e B non è stata concessa né l'autorizzazione P1 né l'autorizzazione P1A.

  • Nell'assembly A è contenuto il metodo A, nell'assembly B è contenuto il metodo B e così via.

Utilizzo di Assert

In questo scenario, il metodo A chiama B, B chiama C, C chiama E ed E chiama F. Il metodo C effettua un'asserzione dell'autorizzazione alla lettura dei file contenuti nell'unità C (autorizzazione P1) e il metodo E impone l'autorizzazione alla lettura dei file TXT contenuti nell'unità C (autorizzazione P1A). Quando in fase di esecuzione viene rilevata la richiesta in F, viene avviata l'analisi dello stack per controllare le autorizzazioni di tutti i chiamanti di F a partire da E. Dal momento che E dispone dell'autorizzazione P1A, l'analisi dello stack procede con l'esame delle autorizzazioni di C, dove viene rilevata l'asserzione di C. Poiché l'autorizzazione richiesta (P1A) è un sottoinsieme dell'autorizzazione oggetto dell'asserzione (P1), l'analisi dello stack si interrompe e automaticamente il controllo di sicurezza ha esito positivo. Non è importante che gli assembly A e B non abbiano ottenuto l'autorizzazione P1A: con l'asserzione di P1, il metodo C garantisce che i chiamanti siano in grado di accedere alla risorsa protetta da P1, anche se non è stata loro concessa la relativa autorizzazione.

Se si progetta una libreria di classi e una classe accede a una risorsa protetta, nella maggior parte dei casi sarà necessario generare una richiesta di sicurezza che imponga ai chiamanti della classe il possesso dell'autorizzazione appropriata. Se successivamente la classe esegue un'operazione per la quale si è certi che la maggior parte dei chiamanti della classe non disponga di autorizzazioni e si è disposti a consentire loro di chiamare il codice, è possibile effettuare un'asserzione dell'autorizzazione chiamando il metodo Assert su un oggetto autorizzazione che rappresenta l'operazione eseguita dal codice. Utilizzando il metodo Assert in questo modo si consente di chiamare il codice a chiamanti che normalmente non disporrebbero dell’autorizzazione necessaria. Quando si effettua quindi l'asserzione di un'autorizzazione, è necessario assicurarsi di avere precedentemente eseguito gli opportuni controlli di sicurezza per impedire l'utilizzo improprio del componente.

Si supponga, ad esempio, che una classe di libreria altamente attendibile disponga di un metodo per l'eliminazione di file. L'accesso al file viene effettuato chiamando una funzione Win32 non gestita. Il metodo Delete del codice viene richiamato da un chiamante, che passa il nome del file da eliminare, C:\Test.txt. All'interno del metodo Delete, il codice crea un oggetto FileIOPermission che rappresenta l'accesso in scrittura a C:\Test.txt. L'accesso in scrittura è necessario per l'eliminazione di file. Viene quindi richiamato un controllo di sicurezza imperativo chiamando il metodo Demand dell'oggetto FileIOPermission. Se uno dei chiamanti inclusi nello stack di chiamate non dispone di questa autorizzazione, viene generato un oggetto SecurityException. Se non viene generata alcuna eccezione, tutti i chiamanti hanno il diritto di accedere a C:\Test.txt. Poiché si prevede che la maggior parte dei chiamanti non disporrà dell'autorizzazione per l'accesso al codice non gestito, viene creato un oggetto SecurityPermission che rappresenta il diritto di chiamare codice non gestito. Viene quindi chiamato il metodo Assert di tale oggetto. Viene poi chiamata la funzione Win32 non gestita per eliminare C:\Text.txt e infine il controllo viene restituito al chiamante.

Attenzione:

È necessario assicurarsi che non vengano utilizzate asserzioni in situazioni in cui è possibile che il codice venga utilizzato da altro codice per accedere a una risorsa protetta dall'autorizzazione oggetto dell'asserzione. È ad esempio necessario che nel codice che consente di scrivere in un file il cui nome è specificato come parametro dal chiamante non venga effettuata l'asserzione di FileIOPermission per la scrittura nei file, poiché il codice sarebbe esposto a un eventuale utilizzo improprio da parte di terzi.

Quando si utilizza la sintassi di sicurezza imperativa, chiamando il metodo Assert su più autorizzazioni nello stesso metodo viene generata un'eccezione di sicurezza. Per evitare questo problema, è possibile creare un oggetto PermissionSet e passare a tale oggetto le singole autorizzazioni che si desidera invocare, quindi effettuare la chiamata al metodo Assert sull'oggetto PermissionSet. È possibile chiamare il metodo Assert più volte quando si utilizza la sintassi di sicurezza dichiarativa.

Nell'esempio riportato di seguito viene illustrato l'utilizzo della sintassi dichiarativa per eseguire l'override dei controlli di sicurezza mediante il metodo Assert. Si noti che la sintassi di FileIOPermissionAttribute assume due valori: un'enumerazione SecurityAction e la posizione del file o della directory per i quali è necessario che venga concessa l'autorizzazione. La chiamata di Assert determina l'esito positivo delle richieste di accesso a C:\Log.txt, anche se i chiamanti non vengono sottoposti a controllo per stabilire se dispongono delle autorizzazioni necessarie per l'accesso.

[Visual Basic]

Option Explicit
Option Strict

Imports System
Imports System.IO
Imports System.Security.Permissions

Namespace LogUtil
   Public Class Log
      Public Sub New()

      End Sub

     <FileIOPermission(SecurityAction.Assert, All := "C:\Log.txt")> Public Sub 
      MakeLog()
         Dim TextStream As New StreamWriter("C:\Log.txt")
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now) '
         TextStream.Close()
      End Sub
   End Class
End Namespace
namespace LogUtil
{
   using System;
   using System.IO;
   using System.Security.Permissions;

   public class Log
   {
      public Log()
      {    
      }   
      [FileIOPermission(SecurityAction.Assert, All = @"C:\Log.txt")]
      public void MakeLog()
      {   
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);
         TextStream.Close();
      }
   }
} 

Nei frammenti di codice seguenti viene illustrato l'utilizzo della sintassi imperativa per eseguire l'override dei controlli di sicurezza mediante il metodo Assert. In tale esempio viene dichiarata un'istanza dell'oggetto FileIOPermission. Al relativo costruttore viene passato FileIOPermissionAccess.AllAccess per definire il tipo di accesso consentito, seguito da una stringa che specifica la posizione del file. Una volta definito l'oggetto FileIOPermission, sarà sufficiente chiamarne il metodo Assert per eseguire l'override dei controlli di sicurezza.

[Visual Basic]

Option Explicit
Option Strict
Imports System
Imports System.IO
Imports System.Security.Permissions
Namespace LogUtil
   Public Class Log
      Public Sub New()
      End Sub 'New
      
      Public Sub MakeLog()
         Dim FilePermission As New FileIOPermission(FileIOPermissionAccess.AllAccess, "C:\Log.txt")
         FilePermission.Assert()
         Dim TextStream As New StreamWriter("C:\Log.txt")
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now)
         TextStream.Close()
      End Sub
   End Class
End Namespace 
namespace LogUtil
{
   using System;
   using System.IO;
   using System.Security.Permissions;

   public class Log
   {
      public Log()
      {    
      }   
      public void MakeLog()
      {
         FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess,@"C:\Log.txt"); 
         FilePermission.Assert();
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);
         TextStream.Close();
      }
   }
}

Vedere anche

Concetti

Override dei controlli di protezione

Pretese di protezione

Riferimenti

PermissionSet

SecurityPermission

FileIOPermission

SecurityAction

Altre risorse

Estensione di metadati mediante attributi

Protezione dall'accesso di codice