Codezugriffssicherheit und ADO.NET

.NET Framework bietet sowohl rollenbasierte Sicherheit als auch Codezugriffssicherheit (Code Access Security, CAS), die beide mit einer von der CLR (Common Language Runtime) bereitgestellten gemeinsamen Infrastruktur implementiert werden. In der Welt des nicht verwalteten Codes werden die meisten Anwendungen mit den Berechtigungen des Benutzers oder Prinzipals ausgeführt. Daher können Computersysteme beschädigt werden und vertrauliche Daten in die falschen Hände gelangen, wenn ein Benutzer mit erweiterten Rechten schädliche oder fehlerhafte Software ausführt.

Im Gegensatz dazu enthält verwalteter Code, der in .NET Framework ausgeführt wird, Codezugriffssicherheit, die nur für den Code gilt. Ob der Code ausgeführt werden darf, hängt vom Ursprung des Codes oder von anderen Aspekten der Identität des Codes und nicht allein von der Identität des Prinzipals ab. Dies verringert die Wahrscheinlichkeit des Missbrauchs von verwaltetem Code.

Hinweis

Die Codezugriffssicherheit (CAS, Code Access Security) ist in allen Versionen von .NET Framework und .NET veraltet. Aktuelle Versionen von .NET berücksichtigen keine CAS-Anmerkungen und erzeugen Fehler, wenn CAS-bezogene APIs verwendet werden. Entwickler*innen sollten alternative Mittel zum Ausführen von Sicherheitsaufgaben suchen.

Codezugriffsberechtigungen

Beim Ausführen von Code wird ein Beweis bereitgestellt, der vom CLR-Sicherheitssystem ausgewertet wird. Dieser Beweis umfasst i. d. R. die Herkunft des Codes, wozu URL, Site, Zone und digitale Signaturen gehören, die die Identität der Assembly gewährleisten.

Die CLR ermöglicht es Code, nur die Vorgänge auszuführen, zu denen er berechtigt ist. Code kann Berechtigungen anfordern, und diese Berechtigungen werden entsprechend der von einem Administrator festgelegten Sicherheitsrichtlinie gewährt.

Hinweis

Code, der in der CLR ausgeführt wird, kann sich nicht selbst Berechtigungen erteilen. So kann Code z. B. weniger Berechtigungen anfordern und gewährt bekommen, als in einer Sicherheitsrichtlinie festgelegt sind, mehr als die darin festgelegten Berechtigungen werden aber auf keinen Fall gewährt. Beim Gewähren von Berechtigungen hat es sich bewährt, zunächst ganz ohne Berechtigungen zu beginnen und immer nur die geringstmöglichen Berechtigungen für die konkrete auszuführende Aufgabe hinzuzufügen. Wenn man stattdessen zu Beginn alle Berechtigungen gewährt und dann nur einzelne Berechtigungen wieder entzieht, entstehen unsichere Anwendungen, die unbeabsichtigte Sicherheitslücken enthalten können, weil mehr Berechtigungen als notwendig gewährt wurden. Weitere Informationen finden Sie unter Konfigurieren von Sicherheitsrichtlinien und Verwaltung von Sicherheitsrichtlinien.

Es gibt die folgenden drei Arten von Codezugriffsberechtigungen:

  • Code access permissions leiten sich aus der CodeAccessPermission-Klasse her. Die Berechtigungen werden benötigt, um auf geschützte Ressourcen, z. B. Dateien und Umgebungsvariablen, zugreifen und geschützte Vorgänge, z. B. das Zugreifen auf nicht verwalteten Code, ausführen zu können.

  • Identity permissions stehen für Eigenschaften, die eine Assembly identifizieren. Die Berechtigungen werden einer Assembly nach Vorlage eines Beweises gewährt. Als Beweise gelten z. B. digitale Signaturen oder der Ursprung des Codes. Identitätsberechtigungen leiten sich auch von der CodeAccessPermission-Basisklasse her.

  • Role-based security permissions basieren darauf, ob ein Prinzipal eine bestimmte Identität besitzt oder Member einer bestimmten Rolle ist. Die Klasse PrincipalPermission ermöglicht sowohl deklarative als auch imperative Berechtigungsprüfungen des aktiven Prinzipals.

Zur Bestimmung, ob Code auf eine Ressource zugreifen oder einen Vorgang ausführen darf, durchläuft das Laufzeit-Sicherheitssystem die Aufrufliste und vergleicht dabei die gewährten Berechtigungen der einzelnen Aufrufer mit den angeforderten Berechtigungen. Wenn einer der Aufrufer in der Aufrufliste die angeforderte Berechtigung nicht besitzt, wird eine SecurityException ausgelöst, und der Zugriff wird verweigert.

Anfordern von Berechtigungen

Zweck der Anforderung von Berechtigungen ist es, die Laufzeit darüber zu informieren, welche Berechtigungen Ihre Anwendung zum Ausführen benötigt, und sicherzustellen, dass die Anwendung nur die Berechtigungen erhält, die sie tatsächlich benötigt. Wenn die Anwendung z. B. Daten auf die lokale Festplatte schreiben muss, benötigt sie die FileIOPermission. Wenn diese Berechtigung nicht gewährt wurde, schlagen alle Versuche, auf die Festplatte zu schreiben, fehl. Wenn die Anwendung die FileIOPermission anfordert und die Berechtigung nicht gewährt wurde, generiert die Anwendung aber von vornherein die Ausnahme und wird nicht geladen.

In einem Szenario, in dem die Anwendung nur Daten vom Datenträger lesen muss, können Sie festlegen, dass der Anwendung niemals Schreibberechtigungen gewährt werden. Auf diese Weise kann Ihr Code im Falle eines Fehlers im Programm oder eines bösartigen Angriffs die Daten, mit denen er arbeitet, nicht beschädigen. Weitere Informationen finden Sie unter Anfordern von Berechtigungen.

Rollenbasierte Sicherheit und CAS

Durch Implementieren der rollenbasierten Sicherheit und der Codezugriffssicherheit (CAS) lässt sich die Gesamtsicherheit Ihrer Anwendung verbessern. Als Grundlage für die rollenbasierte Sicherheit kann ein Windows-Konto oder eine benutzerdefinierte Identität verwendet werden, wodurch die Informationen zum Sicherheitsprinzipal für den aktuellen Thread verfügbar werden. Anwendungen müssen darüber hinaus oft anhand der vom Benutzer bereitgestellten Anmeldeinformationen Daten- oder Ressourcenzugriff gewähren. In der Regel überprüfen diese Anwendungen zunächst die Rolle des Benutzers und stellen dann auf Grundlage dieser Rolle den Zugriff auf Ressourcen bereit.

Die rollenbasierte Sicherheit ermöglicht es einer Komponente, zur Laufzeit aktuelle Benutzer und die ihnen zugeordneten Rollen zu identifizieren. Diese Informationen werden dann mithilfe einer CAS-Richtlinie zugeordnet, um die zur Laufzeit gewährten Berechtigungen zu bestimmen. Für eine bestimmte Anwendungsdomäne kann der Host die Standardrichtlinie der rollenbasierten Sicherheit ändern und einen Standardsicherheitsprinzipal festlegen, der für einen Benutzer und die mit diesem Benutzer verknüpften Rollen steht.

Die CLR verwendet Berechtigungen zum Implementieren ihres Mechanismus zur Durchsetzung von Beschränkungen für verwalteten Code. Rollenbasierte Sicherheitsberechtigungen bieten die Möglichkeit aufzudecken, ob ein Benutzer (oder der Agent, der im Auftrag des Benutzers agiert) eine bestimmte Identität besitzt oder Member einer bestimmten Rolle ist. Weitere Informationen finden Sie unter Sicherheitsberechtigungen.

Je nach Art der Anwendung, die Sie erstellen, sollten Sie in Erwägung ziehen, rollenbasierte Berechtigungen in der Datenbank zu implementieren. Weitere Informationen zur rollenbasierten Sicherheit in SQL Server finden Sie unter SQL Server-Sicherheit.

Assemblys

Assemblys bilden die Grundlage für die Bereitstellung, die Versionskontrolle, die Wiederverwendung, die Festlegung des Aktivierungsumfangs und die Sicherheitsberechtigungen für eine .NET Framework-Anwendung. Eine Assembly stellt eine Sammlung von Typen und Ressourcen bereit, die zusammenarbeiten und eine logische Funktionalitätseinheit bilden. Für die CLR existiert ein Typ niemals außerhalb des Kontexts einer Assembly. Weitere Informationen zum Erstellen und Bereitstellen von Assemblys finden Sie unter Programmierung mit Assemblys.

Assemblys mit starkem Namen

Ein starker Name (oder eine digitale Signatur) setzt sich aus der Identität der Assembly mit einfachem Textnamen, Versionsnummer und (sofern vorhanden) Kulturinformationen sowie einem öffentlichen Schlüssel und einer digitalen Signatur zusammen. Die digitale Signatur wird mit dem entsprechenden privaten Schlüssel aus einer Assemblydatei generiert. Die Assemblydatei enthält das Assemblymanifest, das wiederum die Namen und Hashes aller Dateien enthält, die die Assembly bilden.

Wenn eine Assembly mit einem starken Namen versehen wird, erhalten Anwendungen oder Komponenten eine eindeutige Identität, über die andere Software explizit auf die Assembly verweisen können. Ein starker Name schützt Assemblys vor Angriffen durch andere Assemblys, die bösartigen Code enthalten. Außerdem wird durch starke Namen die Versionskonsistenz zwischen verschiedenen Versionen einer Komponente gewährleistet. Assemblys, die im globalen Assemblycache (GAC) bereitgestellt werden sollen, müssen einen starken Namen erhalten. Weitere Informationen finden Sie unter Erstellen und Verwenden von Assemblys mit starkem Namen.

Teilweise Vertrauenswürdigkeit in ADO.NET 2.0

In ADO.NET 2.0 können der .NET Framework-Datenanbieter für SQL Server, der .NET Framework-Datenanbieter für OLE DB, der .NET Framework-Datenanbieter für ODBC und der .NET Framework-Datenanbieter für Oracle jetzt alle in teilweise vertrauenswürdigen Umgebungen ausgeführt werden. In früheren Releases von .NET Framework wurde nur System.Data.SqlClient in nicht vollständig vertrauenswürdigen Umgebungen unterstützt.

Eine teilweise vertrauenswürdige Anwendung, die den Datenanbieter für SQL Server verwendet, muss mindestens die Berechtigung zum Ausführen und die SqlClientPermission-Berechtigung besitzen.

Eigenschaften von Berechtigungsattributen für teilweise Vertrauenswürdigkeit

In Szenarien für teilweise Vertrauenswürdigkeit können Sie SqlClientPermissionAttribute-Member zur weiteren Einschränkung der verfügbaren Funktionen des .NET Framework-Datenanbieters für SQL Server verwenden.

In der folgenden Tabelle werden die verfügbaren SqlClientPermissionAttribute-Eigenschaften mit ihren Beschreibungen aufgeführt:

Berechtigungsattributeigenschaft BESCHREIBUNG
Action Ruft eine Sicherheitsaktion ab oder legt diese fest. Wird von SecurityAttribute geerbt.
AllowBlankPassword Aktiviert oder deaktiviert die Verwendung von leeren Kennwörtern in einer Verbindungszeichenfolge. Gültige Werte sind true (zum Aktivieren der Verwendung von leeren Kennwörtern) und false (zum Deaktivieren der Verwendung von leeren Kennwörtern). Wird von DBDataPermissionAttribute geerbt.
ConnectionString Gibt eine zulässige Verbindungszeichenfolge an. Es können mehrere Verbindungszeichenfolgen angegeben werden. Hinweis: Die Verbindungszeichenfolge darf keine Benutzer-ID und kein Kennwort enthalten. In diesem Release können Einschränken von Verbindungszeichenfolgen nicht mit dem .NET Framework-Konfigurationstool geändert werden.

Wird von DBDataPermissionAttribute geerbt.
KeyRestrictions Gibt zulässige oder unzulässige Parameter für Verbindungszeichenfolgen an. Parameter für Verbindungszeichenfolgen werden im Format <Parametername>= angegeben. Es können mehrere durch Semikolon (;) getrennte Parameter angegeben werden. Hinweis: Wenn Sie keine KeyRestrictions angeben, die KeyRestrictionBehavior-Eigenschaft aber auf AllowOnly oder PreventUsage festlegen, sind keine zusätzlichen Parameter für die Verbindungszeichenfolge zulässig. Wird von DBDataPermissionAttribute geerbt.
KeyRestrictionBehavior Legt die Verbindungszeichenfolgenparameter als die einzigen zulässigen zusätzlichen Parameter fest (AllowOnly) oder gibt die nicht zulässigen zusätzlichen Parameter an (PreventUsage). AllowOnly ist die Standardoption. Wird von DBDataPermissionAttribute geerbt.
TypeID Ruft bei Implementierung in einer abgeleiteten Klasse einen eindeutigen Bezeichner für dieses Attribut ab. Wird von Attribute geerbt.
Unrestricted Gibt an, ob für die Ressource uneingeschränkte Berechtigungen deklariert wurden. Wird von SecurityAttribute geerbt.

Syntax von "ConnectionString"

Das folgende Beispiel zeigt, wie mithilfe des Elements connectionStrings einer Konfigurationsdatei nur eine bestimmte Verbindungszeichenfolge für die Verwendung zugelassen werden kann. Weitere Informationen zum Speichern und Abrufen von Verbindungszeichenfolgen in Konfigurationsdateien finden Sie unter Verbindungszeichenfolgen.

<connectionStrings>  
  <add name="DatabaseConnection"
    connectionString="Data Source=(local);Initial
    Catalog=Northwind;Integrated Security=true;" />  
</connectionStrings>  

Syntax von "KeyRestrictions"

Im folgenden Beispiel wird dieselbe Verbindungszeichenfolge sowie die Verwendung der Verbindungszeichenfolgenoptionen Encrypt und Packet Size aktiviert, dabei aber die Verwendung aller anderen Verbindungszeichenfolgenoptionen eingeschränkt.

<connectionStrings>  
  <add name="DatabaseConnection"
    connectionString="Data Source=(local);Initial
    Catalog=Northwind;Integrated Security=true;"  
    KeyRestrictions="Encrypt=;Packet Size=;"  
    KeyRestrictionBehavior="AllowOnly" />  
</connectionStrings>  

Syntax von "KeyRestrictionBehavior" mit "PreventUsage"

Im folgenden Beispiel wird dieselbe Verbindungszeichenfolge aktiviert, und alle anderen Verbindungsparameter bis auf User Id, Password und Persist Security Info werden zugelassen.

<connectionStrings>  
  <add name="DatabaseConnection"
    connectionString="Data Source=(local);Initial
    Catalog=Northwind;Integrated Security=true;"  
    KeyRestrictions="User Id=;Password=;Persist Security Info=;"  
    KeyRestrictionBehavior="PreventUsage" />  
</connectionStrings>  

Syntax von "KeyRestrictionBehavior" mit "AllowOnly"

Im folgenden Beispiel werden zwei Verbindungszeichenfolgen aktiviert, die außerdem die Parameter Initial Catalog, Connection Timeout, Encrypt und Packet Size enthalten. Alle anderen Parameter für Verbindungszeichenfolgen werden nicht zugelassen.

<connectionStrings>  
  <add name="DatabaseConnection"
    connectionString="Data Source=(local);Initial
    Catalog=Northwind;Integrated Security=true;"  
    KeyRestrictions="Initial Catalog;Connection Timeout=;  
       Encrypt=;Packet Size=;"
    KeyRestrictionBehavior="AllowOnly" />  
  
  <add name="DatabaseConnection2"
    connectionString="Data Source=SqlServer2;Initial
    Catalog=Northwind2;Integrated Security=true;"  
    KeyRestrictions="Initial Catalog;Connection Timeout=;  
       Encrypt=;Packet Size=;"
    KeyRestrictionBehavior="AllowOnly" />  
</connectionStrings>  

Aktivieren einer teilweisen Vertrauenswürdigkeit mit einem benutzerdefinierten Berechtigungssatz

Um die Verwendung der System.Data.SqlClient-Berechtigungen für eine bestimmte Zone zu aktivieren, muss ein Systemadministrator einen benutzerdefinierten Berechtigungssatz für eine bestimmte Zone erstellen. Standardberechtigungssätze wie LocalIntranet können nicht geändert werden. Um beispielsweise System.Data.SqlClient-Berechtigungen für Code mit einer auf LocalIntranet festgelegten Zone hinzuzufügen, kann ein Systemadministrator den Berechtigungssatz für LocalIntranet kopieren, ihn in „CustomLocalIntranet“ umbenennen, die System.Data.SqlClient-Berechtigungen hinzufügen, den CustomLocalIntranet-Berechtigungssatz mit Caspol.exe (Tool für Codezugriffssicherheits-Richtlinien) importieren und den Berechtigungssatz von LocalIntranet_Zone auf „CustomLocalIntranet“ festlegen.

Beispielberechtigungssatz

Im Folgenden finden Sie einen Beispielberechtigungssatz für den .NET Framework-Datenanbieter für SQL Server in einem teilweise vertrauenswürdigen Szenario. Informationen zum Erstellen benutzerdefinierter Berechtigungssätze finden Sie unter Konfigurieren von Berechtigungssätzen mithilfe von „Caspol.exe“.

<PermissionSet class="System.Security.NamedPermissionSet"  
  version="1"  
  Name="CustomLocalIntranet"  
  Description="Custom permission set given to applications on  
    the local intranet">  
  
<IPermission class="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"  
version="1"  
AllowBlankPassword="False">  
<add ConnectionString="Data Source=(local);Integrated Security=true;"  
 KeyRestrictions="Initial Catalog=;Connection Timeout=;  
   Encrypt=;Packet Size=;"
 KeyRestrictionBehavior="AllowOnly" />  
 </IPermission>  
</PermissionSet>  

Überprüfen des ADO.NET-Codezugriffs mit Sicherheitsberechtigungen

In teilweise vertrauenswürdigen Szenarien können durch Angabe eines SqlClientPermissionAttribute für bestimmte Methoden im Code CAS-Berechtigungen verlangt werden. Wenn diese Berechtigung aufgrund einer eingeschränkten Sicherheitsrichtlinie nicht gewährt wird, wird vor dem Ausführen des Codes eine Ausnahme ausgelöst. Weitere Informationen zur Sicherheitsrichtlinie finden Sie unter Verwaltung von Sicherheitsrichtlinien und Bewährte Methoden für Sicherheitsrichtlinien.

Beispiel

Im folgenden Beispiel wird das Schreiben von Code gezeigt, durch den eine bestimmte Verbindungszeichenfolge verlangt wird. Der Code simuliert das Verweigern uneingeschränkter Berechtigungen für System.Data.SqlClient. Unter Praxisbedingungen würde dies durch eine CAS-Richtlinie implementiert werden.

Wichtig

Die korrekte Vorgehensweise beim Entwerfen von CAS-Berechtigungen für ADO.NET besteht darin, vom restriktivsten Fall (gar keine Berechtigungen) auszugehen und dann nur die Berechtigungen hinzuzufügen, die für die konkreten auszuführenden Aufgaben erforderlich sind. Die umgekehrte Herangehensweise, also zuerst alle Berechtigungen zu gewähren und dann zu versuchen, eine bestimmte Berechtigung zu verweigern, ist dagegen unsicher, da ein und dieselbe Verbindungszeichenfolge auf verschiedene Art und Weise ausgedrückt werden kann. Wenn Sie z. B. alle Berechtigungen zulassen und dann die Verwendung der Verbindungszeichenfolge "server=someserver" zu verweigern versuchen, wäre die Zeichenfolge "server=someserver.mycompany.com" nach wie vor zulässig. Wenn Sie hingegen immer ohne jede Berechtigung beginnen, sinkt die Gefahr, dass der Berechtigungssatz Lücken enthält.

Der folgende Code zeigt, wie SqlClient die Sicherheitsanforderung ausführt, die eine SecurityException auslöst, wenn die entsprechenden CAS-Berechtigungen nicht vorhanden sind. Die Ausgabe des SecurityException-Objekts wird im Konsolenfenster angezeigt.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Security;
using System.Security.Permissions;

namespace PartialTrustTopic {
   public class PartialTrustHelper : MarshalByRefObject {
      public void TestConnectionOpen(string connectionString) {
         // Try to open a connection.
         using (SqlConnection connection = new SqlConnection(connectionString)) {
            connection.Open();
         }
      }
   }

   class Program {
      static void Main(string[] args) {
         TestCAS("Data Source=(local);Integrated Security=true", "Data Source=(local);Integrated Security=true;Initial Catalog=Test");
      }

      static void TestCAS(string connectString1, string connectString2) {
         // Create permission set for sandbox AppDomain.
         // This example only allows execution.
         PermissionSet permissions = new PermissionSet(PermissionState.None);
         permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

            // Create sandbox AppDomain with permission set that only allows execution,
            // and has no SqlClientPermissions.
            AppDomainSetup appDomainSetup = new AppDomainSetup();
         appDomainSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
         AppDomain firstDomain = AppDomain.CreateDomain("NoSqlPermissions", null, appDomainSetup, permissions);

         // Create helper object in sandbox AppDomain so that code can be executed in that AppDomain.
         Type helperType = typeof(PartialTrustHelper);
         PartialTrustHelper firstHelper = (PartialTrustHelper)firstDomain.CreateInstanceAndUnwrap(helperType.Assembly.FullName, helperType.FullName);

         try {
            // Attempt to open a connection in the sandbox AppDomain.
            // This is expected to fail.
            firstHelper.TestConnectionOpen(connectString1);
            Console.WriteLine("Connection opened, unexpected.");
         }
         catch (System.Security.SecurityException ex) {
            Console.WriteLine("Failed, as expected: {0}",
                ex.FirstPermissionThatFailed);

            // Uncomment the following line to see Exception details.
            // Console.WriteLine("BaseException: " + ex.GetBaseException());
         }

         // Add permission for a specific connection string.
         SqlClientPermission sqlPermission = new SqlClientPermission(PermissionState.None);
         sqlPermission.Add(connectString1, "", KeyRestrictionBehavior.AllowOnly);

         permissions.AddPermission(sqlPermission);

         AppDomain secondDomain = AppDomain.CreateDomain("OneSqlPermission", null, appDomainSetup, permissions);
         PartialTrustHelper secondHelper = (PartialTrustHelper)secondDomain.CreateInstanceAndUnwrap(helperType.Assembly.FullName, helperType.FullName);

         // Try connection open again, it should succeed now.
         try {
            secondHelper.TestConnectionOpen(connectString1);
            Console.WriteLine("Connection opened, as expected.");
         }
         catch (System.Security.SecurityException ex) {
            Console.WriteLine("Unexpected failure: {0}", ex.Message);
         }

         // Try a different connection string. This should fail.
         try {
            secondHelper.TestConnectionOpen(connectString2);
            Console.WriteLine("Connection opened, unexpected.");
         }
         catch (System.Security.SecurityException ex) {
            Console.WriteLine("Failed, as expected: {0}", ex.Message);
         }
      }
   }
}
Imports System.Data
Imports System.Data.SqlClient
Imports System.Security
Imports System.Security.Permissions

Namespace PartialTrustTopic
    Public Class PartialTrustHelper
        Inherits MarshalByRefObject
        Public Sub TestConnectionOpen(ByVal connectionString As String)
            ' Try to open a connection.
            Using connection As New SqlConnection(connectionString)
                connection.Open()
            End Using
        End Sub
    End Class

    Class Program
        Public Shared Sub Main(ByVal args As String())
            TestCAS("Data Source=(local);Integrated Security=true", "Data Source=(local);Integrated Security=true;Initial Catalog=Test")
        End Sub

        Public Shared Sub TestCAS(ByVal connectString1 As String, ByVal connectString2 As String)
            ' Create permission set for sandbox AppDomain.
            ' This example only allows execution.
            Dim permissions As New PermissionSet(PermissionState.None)
            permissions.AddPermission(New SecurityPermission(SecurityPermissionFlag.Execution))

            ' Create sandbox AppDomain with permission set that only allows execution,
            ' and has no SqlClientPermissions.
            Dim appDomainSetup As New AppDomainSetup()
            appDomainSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
            Dim firstDomain As AppDomain = AppDomain.CreateDomain("NoSqlPermissions", Nothing, appDomainSetup, permissions)

            ' Create helper object in sandbox AppDomain so that code can be executed in that AppDomain.
            Dim helperType As Type = GetType(PartialTrustHelper)
            Dim firstHelper As PartialTrustHelper = DirectCast(firstDomain.CreateInstanceAndUnwrap(helperType.Assembly.FullName, helperType.FullName), PartialTrustHelper)

            Try
                ' Attempt to open a connection in the sandbox AppDomain.
                ' This is expected to fail.
                firstHelper.TestConnectionOpen(connectString1)
                Console.WriteLine("Connection opened, unexpected.")
            Catch ex As System.Security.SecurityException

                ' Uncomment the following line to see Exception details.
                ' Console.WriteLine("BaseException: " + ex.GetBaseException());
                Console.WriteLine("Failed, as expected: {0}", ex.FirstPermissionThatFailed)
            End Try

            ' Add permission for a specific connection string.
            Dim sqlPermission As New SqlClientPermission(PermissionState.None)
            sqlPermission.Add(connectString1, "", KeyRestrictionBehavior.AllowOnly)

            permissions.AddPermission(sqlPermission)

            Dim secondDomain As AppDomain = AppDomain.CreateDomain("OneSqlPermission", Nothing, appDomainSetup, permissions)
            Dim secondHelper As PartialTrustHelper = DirectCast(secondDomain.CreateInstanceAndUnwrap(helperType.Assembly.FullName, helperType.FullName), PartialTrustHelper)

            ' Try connection open again, it should succeed now.
            Try
                secondHelper.TestConnectionOpen(connectString1)
                Console.WriteLine("Connection opened, as expected.")
            Catch ex As System.Security.SecurityException
                Console.WriteLine("Unexpected failure: {0}", ex.Message)
            End Try

            ' Try a different connection string. This should fail.
            Try
                secondHelper.TestConnectionOpen(connectString2)
                Console.WriteLine("Connection opened, unexpected.")
            Catch ex As System.Security.SecurityException
                Console.WriteLine("Failed, as expected: {0}", ex.Message)
            End Try
        End Sub
    End Class
End Namespace

Im Konsolenfenster müsste nun die folgende Ausgabe angezeigt werden:

Failed, as expected: <IPermission class="System.Data.SqlClient.  
SqlClientPermission, System.Data, Version=2.0.0.0,
  Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"  
  AllowBlankPassword="False">  
<add ConnectionString="Data Source=(local);Initial Catalog=  
  Northwind;Integrated Security=SSPI" KeyRestrictions=""  
KeyRestrictionBehavior="AllowOnly"/>  
</IPermission>  
  
Connection opened, as expected.  
Failed, as expected: Request failed.  

Interoperabilität mit nicht verwaltetem Code

Code, der außerhalb der CLR ausgeführt wird, wird als nicht verwalteter Code bezeichnet. Deshalb können Sicherheitsmechanismen, z. B. CAS, auf nicht verwalteten Code nicht angewendet werden. Beispiele für nicht verwalteten Code sind COM-Komponenten, ActiveX-Schnittstellen und Windows API-Funktionen. Damit bei der Ausführung von nicht verwaltetem Code die Gesamtsicherheit der Anwendung nicht gefährdet wird, sind besondere Sicherheitsüberlegungen notwendig. Weitere Informationen finden Sie unter Interoperation mit nicht verwaltetem Code.

.NET Framework unterstützt den Zugriff durch COM-Interop, um die Abwärtskompatibilität zu vorhandenen COM-Komponenten sicherzustellen. Sie können COM-Komponenten in eine .NET Framework-Anwendung einbauen, indem Sie die entsprechenden COM-Typen mit den COM-Interop-Tools importieren. Nach dem Import sind die COM-Typen einsatzbereit. COM-Interop ermöglicht es COM-Clients auch, auf verwalteten Code zuzugreifen, indem Assemblymetadaten in eine Typbibliothek exportiert und die verwalteten Komponenten als COM-Komponente registriert werden. Weitere Informationen finden Sie unter Erweiterte COM-Interoperabilität.

Siehe auch