Utilisation de la méthode Assert
Mise à jour : novembre 2007
Assert est une méthode qui peut être appelée sur les classes d'autorisation d'accès du code et sur la classe PermissionSet. Vous pouvez utiliser Assert pour permettre à votre code (et aux appelants en aval) d'effectuer des actions qu'il est autorisé à faire, mais que ses appelants peuvent ne pas être autorisés à faire. Une assertion de sécurité change le processus normal effectué par le runtime lors d'une vérification de la sécurité. Lorsque vous déclarez une autorisation, elle indique au système de sécurité de ne pas vérifier que les appelants de votre code ont l'autorisation déclarée.
Attention : |
---|
Utilisez les assertions avec précaution, car elles peuvent ouvrir une faille de sécurité et ébranler le mécanisme d'application des restrictions de sécurité du runtime. |
Les assertions sont utiles lorsqu'une bibliothèque appelle dans du code non managé ou effectue un appel qui nécessite une autorisation qui n'est apparemment pas en relation avec l'utilisation prévue de la bibliothèque. Par exemple, tout le code managé qui appelle dans du code non managé doit avoir SecurityPermission avec l'indicateur UnmanagedCode spécifié. Du code qui ne provient pas de l'ordinateur local, comme du code téléchargé à partir d'Internet, ne recevra pas cette autorisation par défaut. En conséquence, pour que du code téléchargé localement à partir de l'intranet local puisse appeler une bibliothèque qui utilise du code non managé, il doit avoir l'autorisation déclarée par la bibliothèque. De plus, certaines bibliothèques peuvent effectuer des appels invisibles aux appelants et requièrent des autorisations spéciales.
Vous pouvez aussi utiliser des assertions lorsque votre code accède à une ressource de manière complètement masquée par rapport aux appelants. Supposons par exemple que votre bibliothèque obtienne des informations d'une base de données, mais que dans le processus, elle lise aussi les informations du Registre de l'ordinateur. Étant donné que les développeurs qui utilisent votre bibliothèque n'ont pas accès à votre source, ils n'ont aucun moyen de savoir que leur code nécessite RegistryPermission pour pouvoir utiliser votre code. Dans ce cas, si vous décidez qu'il n'est pas raisonnable ou nécessaire d'exiger que les appelants de votre code aient l'autorisation d'accéder au Registre, vous pouvez déclarer l'autorisation de lire le Registre. Dans ce cas, il est approprié que la bibliothèque déclare l'autorisation, de sorte que les appelants sans RegistryPermission puissent utiliser la bibliothèque.
L'assertion affecte le parcours de pile uniquement si l'autorisation déclarée et une autorisation demandée par un appelant en aval sont du même type et si l'autorisation demandée est un sous-ensemble de l'autorisation déclarée. Par exemple, si vous déclarez FileIOPermission pour lire tous les fichiers sur le lecteur C et si une demande en aval est faite pour FileIOPermission afin de lire les fichiers dans C:\Temp, l'assertion peut affecter le parcours de pile. Cependant, si la demande concerne FileIOPermission pour écrire sur le lecteur C, l'assertion n'a aucun effet.
Pour effectuer des assertions, votre code doit disposer à la fois de l'autorisation que vous déclarez et de la SecurityPermission qui représente le droit d'effectuer des assertions. Bien que vous puissiez déclarer une autorisation qui n'a pas été octroyée à votre code, l'assertion est inutile puisque la vérification de la sécurité échouera avant que l'assertion ne puisse la faire réussir.
L'illustration suivante montre ce qui se passe lorsque vous utilisez Assert. Supposez que les instructions suivantes soient vraies concernant les assemblys A, B, C, E et F et deux autorisations P1 et P1A :
P1A représente le droit de lire les fichiers .txt sur le lecteur C.
P1 représente le droit de lire tous les fichiers sur le lecteur C.
P1A et P1 sont tous deux des types FileIOPermissions et P1A est un sous-ensemble de P1.
Les assemblys E et F ont reçu l'autorisation P1A.
L'assembly C a reçu l'autorisation P1.
Les assemblys A et B n'ont reçu aucune des autorisations P1 et P1A.
La méthode A est contenue dans l'assembly A, la méthode B est contenue dans l'assembly B et ainsi de suite.
Utilisation de Assert
Dans ce scénario, la méthode A appelle B, B appelle C, C appelle E et E appelle F. La méthode C déclare l'autorisation de lire les fichiers sur le lecteur C (autorisation P1) et la méthode E demande l'autorisation de lire les fichiers .txt sur le lecteur C (autorisation P1A). Lorsque la demande dans F est trouvée au moment de l'exécution, un parcours de pile est effectué afin de vérifier les autorisations de tous les appelants F, en commençant par E. E reçoit l'autorisation P1A, le parcours de pile se poursuit pour examiner les autorisations de C où l'assertion de C est trouvée. Puisque l'autorisation demandée (P1A) est un sous-ensemble de l'autorisation déclarée (P1), le parcours de pile s'arrête et la vérification de la sécurité réussit automatiquement. Le fait que l'autorisation P1A n'ait pas été octroyée aux assemblys A et B n'a pas d'importance. En déclarant P1, la méthode C garantit que ses appelants peuvent accéder à la ressource protégée par P1, même si les appelants n'ont pas reçu l'autorisation d'accéder à cette ressource.
Si vous concevez une bibliothèque de classes et si une classe accède à une ressource protégée, vous devez, dans la plupart des cas, faire une demande de sécurité exigeant que les appelants de la classe aient l'autorisation appropriée. Si la classe effectue alors une opération pour laquelle vous savez que la plupart de ses appelants n'auront pas l'autorisation et si vous êtes prédisposé à prendre la responsabilité de laisser ces appelants appeler votre code, vous pouvez déclarer l'autorisation en appelant la méthode Assert sur un objet d'autorisation qui représente l'opération que le code est en train d'effectuer. Cette utilisation de Assert laisse les appelants appeler votre code alors qu'ils ne pourraient normalement pas le faire. Par conséquent, si vous déclarez une autorisation, vous devez être sûr d'effectuer au préalable les vérifications de sécurité appropriées afin d'éviter que votre composant ne soit utilisé de manière abusive.
Supposons par exemple que la classe de votre bibliothèque dont le niveau de confiance est élevé ait une méthode qui supprime les fichiers. Elle accède au fichier en appelant une fonction Win32 non managée. Un appelant appelle la méthode Delete de votre code, en passant le nom du fichier à supprimer, C:\Test.txt. Dans la méthode Delete, votre code crée un objet FileIOPermission représentant l'accès en écriture à C:\Test.txt. L'accès en écriture est requis pour supprimer un fichier. Votre code appelle alors une vérification de sécurité impérative en appelant la méthode Demand de l'objet FileIOPermission. Si l'un des appelants dans la pile des appels n'a pas cette autorisation, une SecurityException est levée. Si aucune exception n'est levée, tous les appelants sont autorisés à accéder à C:\Test.txt. Comme la plupart de vos appelants n'auront pas l'autorisation d'accéder à du code non managé, votre code crée un objet SecurityPermission qui représente le droit d'appeler du code non managé et appelle la méthode Assert de l'objet. Il appelle finalement la fonction Win32 non managée pour supprimer C:\Text.txt et retourne le contrôle à l'appelant.
Attention : |
---|
Vous devez être sûr que votre code n'utilise pas d'assertions dans des situations où il peut être utilisé par un autre code pour accéder à une ressource protégée par l'autorisation que vous déclarez. Par exemple, dans du code qui écrit dans un fichier dont le nom est spécifié comme paramètre par l'appelant, vous ne déclarerez pas FileIOPermission pour écrire dans les fichiers, car votre code pourrait être ouvert à une utilisation malveillante de la part d'un tiers. |
Lorsque vous utilisez la syntaxe de sécurité impérative, l'appel de la méthode Assert pour plusieurs autorisations au sein de la même méthode provoque la levée d'une exception de sécurité. Nous vous conseillons de créer à la place un objet PermissionSet, de lui passer les autorisations individuelles que vous souhaitez appeler, puis d'appeler la méthode Assert sur l'objet PermissionSet. Vous pouvez appeler la méthode Assert plusieurs fois lorsque vous utilisez la syntaxe de sécurité déclarative.
L'exemple suivant illustre la syntaxe déclarative de substitution des vérifications de sécurité à l'aide de la méthode Assert. Notez que la syntaxe FileIOPermissionAttribute prend deux valeurs : une énumération SecurityAction et l'emplacement du fichier ou du répertoire auquel l'autorisation doit être accordée. L'appel à Assert a pour conséquence la réussite des demandes d'accès à C:\Log.txt, même si l'autorisation d'accès des appelants au fichier n'a pas été vérifiée.
[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();
}
}
}
Les fragments de code suivants illustrent la syntaxe impérative de substitution des vérifications de sécurité à l'aide de la méthode Assert. Dans cet exemple, une instance de l'objet FileIOPermission est déclarée. FileIOPermissionAccess.AllAccess est passé à son constructeur pour définir le type d'accès autorisé, suivi d'une chaîne décrivant l'emplacement du fichier. Une fois l'objet FileIOPermission défini, vous n'avez qu'à appeler sa méthode Assert pour substituer la vérification de la sécurité.
[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();
}
}
}
Voir aussi
Concepts
Substitution des vérifications de sécurité