Поделиться через


Практическое руководство. Запрос необязательных разрешений с помощью флага RequestOptional

Важно!

В версии .NET Framework 4 удалена поддержка среды выполнения для принудительного применения запросов разрешений Deny, RequestMinimum, RequestOptional и RequestRefuse.Эти запросы нельзя использовать в коде, основанном на .NET Framework 4 или более поздних версиях.Дополнительные сведения об этом и других изменениях см. в разделе Изменения системы безопасности в платформе .NET Framework 4.

Флаг RequestOptional позволяет запрашивать набор разрешений, неявным образом отклоняя все остальные разрешения, которые в противном случае среда выполнения может попытаться предоставить.Флаг RequestRefuse, напротив, позволяет отклонять разрешения, явно указывая, какие из них не должны выдаваться коду.

Для определения разрешений, которые требуется предоставить в дополнение к необязательным разрешениям, указанным с помощью флага RequestOptional, необходимо использовать флаг RequestMinimum.Код будет загружен и запущен, даже если у него не имеется разрешения, определенного флагом RequestOptional.Если приложение попытается получить доступ к ресурсу, для доступа к которому у него не имеется разрешения, будет создано исключение SecurityException.При использовании разрешений RequestOptional необходимо обеспечить в коде перехват всех исключений, которые будут созданы, если коду не будет выдано необязательное разрешение.

В примере Test из нижеследующей процедуры запрашивается разрешение UIPermission с помощью флага RequestMinimum и разрешение FileIOPermission с помощью флага RequestOptional. Поэтому запросы на все другие разрешения неявным образом отклоняются.С помощью кода из блока try метода Main предпринимается попытка создать новый файл.В случае неудачи блок catch перехватит созданное исключение SecurityException и выведет сообщение.

Запуск приложения в "песочнице"

  1. Создайте проект консольного приложения в Visual Studio.

  2. Скопируйте код из раздела Пример в файл приложения.Этот код создает "песочницу", выполняемую с набором разрешений LocalIntranet.Набор разрешений LocalIntranet не включает разрешение FileIOPermission.

  3. В меню Проект щелкните пункт Свойства, перейдите на вкладку Подписывание и подпишите проект ключом строго имени.

  4. Добавьте в решение новый проект консольного приложения с именем Test.

  5. Скопируйте следующий код в файл приложения для проекта Test.В этом коде запрашивается FileIOPermission в качестве необязательного разрешения.Приложение будет запущено, даже если ему не предоставлено разрешение FileIOPermission.

    Imports System
    Imports System.Security.Permissions
    Imports System.IO
    
    <Assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted:=True)> 
    Namespace Test
        Class Program
    
            Shared Sub Main(ByVal args() As String)
                Console.WriteLine("Test is loaded.")
                File.Create("test.txt")
    
            End Sub 'Main
        End Class 'Program
    End Namespace
    
    
    using System;
    using System.Security.Permissions;
    using System.IO;
    [assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted=true)]
    namespace Test
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Test is loaded.");
                File.Create("test.txt");
            }
        }
    }
    
  6. Запустите приложение "песочницы".Оно загрузит и запустит тестовое приложение.После запуска приложения создается исключение со следующим сообщением:

    Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed. 
    

Дополнительные сведения о запуске приложений в "песочнице" см. в разделе Практическое руководство. Выполнение не вполне безопасного кода в изолированной среде.

Пример

В следующем примере создается "песочница", выполняемая с набором разрешений LocalIntranet.

Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Reflection
Imports System.IO



Class Program

    Shared Sub Main(ByVal args() As String)
        ' Create the permission set to grant to other assemblies.
        ' In this case we are granting the permissions found in the LocalIntranet zone.
        Dim e As New Evidence()
        e.AddHostEvidence(New Zone(SecurityZone.Intranet))
        Dim pset As PermissionSet = SecurityManager.GetStandardSandbox(e)
        ' Optionally you can create your own permission set by explicitly adding permissions.
        '     PermissionSet pset = new PermissionSet(PermissionState.None);
        '     pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
        '     pset.AddPermission(new UIPermission(PermissionState.Unrestricted));
        Dim ads As New AppDomainSetup()
        ' Identify the folder to use for the sandbox.
        ads.ApplicationBase = "C:\Sandbox"
        ' Copy the application to be executed to the sandbox.
        File.Copy("..\..\..\HelloWorld\Bin\Debug\HelloWorld.exe", "C:\sandbox\HelloWorld.exe", True)

        Dim hostEvidence As New Evidence()
        ' Commenting out the following statement has no effect on the sample.
        ' The grant set is determined by the grantSet parameter, not the evidence 
        ' for the assembly.  However, the evidence can be used for other reasons, 
        ' for example, isolated storage.
        hostEvidence.AddHostEvidence(New Zone(SecurityZone.Intranet))


        ' Create the sandboxed domain.
        ' You can replace the null parameter with a strong name that identifies full trust assemblies: 
        ' GetStrongName(Assembly.GetExecutingAssembly()));  This identifies any assemblies in the folder
        ' that are signed with the same strong name as this assembly as being full trust assemblies.
        Dim sandbox As AppDomain = AppDomain.CreateDomain("Sandboxed Domain", hostEvidence, ads, pset, Nothing)

        sandbox.ExecuteAssemblyByName("HelloWorld")

    End Sub 'Main


    Public Shared Function GetStrongName(ByVal [assembly] As [Assembly]) As StrongName
        If [assembly] Is Nothing Then
            Throw New ArgumentNullException("assembly")
        End If
        Dim assemblyName As AssemblyName = [assembly].GetName()
        Debug.Assert(Not (assemblyName Is Nothing), "Could not get assembly name")

        ' Get the public key blob.
        Dim publicKey As Byte() = assemblyName.GetPublicKey()
        If publicKey Is Nothing OrElse publicKey.Length = 0 Then
            Throw New InvalidOperationException("Assembly is not strongly named")
        End If
        Dim keyBlob As New StrongNamePublicKeyBlob(publicKey)

        ' Return the strong name.
        Return New StrongName(keyBlob, assemblyName.Name, assemblyName.Version)

    End Function 'GetStrongName
End Class 'Program 
using System;
using System.Collections;
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Reflection;
using System.IO;

namespace SimpleSandboxing
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the permission set to grant to other assemblies.
            // In this case we are granting the permissions found in the LocalIntranet zone.
            Evidence e = new Evidence();
            e.AddHostEvidence(new Zone(SecurityZone.Intranet));
            PermissionSet pset = SecurityManager.GetStandardSandbox(e);
            // Optionally you can create your own permission set by explicitly adding permissions.
            //     PermissionSet pset = new PermissionSet(PermissionState.None);
            //     pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
            //     pset.AddPermission(new UIPermission(PermissionState.Unrestricted));
            AppDomainSetup ads = new AppDomainSetup();
            // Identify the folder to use for the sandbox.
            ads.ApplicationBase = "C:\\Sandbox";
            // Copy the application to be executed to the sandbox.
            File.Copy("..\\..\\..\\HelloWorld\\Bin\\Debug\\HelloWorld.exe", "C:\\sandbox\\HelloWorld.exe", true);

            Evidence hostEvidence = new Evidence();
            // Commenting out the following statement has no effect on the sample.
            // The grant set is determined by the grantSet parameter, not the evidence 
            // for the assembly.  However, the evidence can be used for other reasons, 
            // for example, isolated storage.
            hostEvidence.AddHostEvidence(new Zone(SecurityZone.Intranet));


            // Create the sandboxed domain.
            // You can replace the null parameter with a strong name that identifies full trust assemblies: 
            // GetStrongName(Assembly.GetExecutingAssembly()));  This identifies any assemblies in the folder
            // that are signed with the same strong name as this assembly as being full trust assemblies.
            AppDomain sandbox = AppDomain.CreateDomain(
               "Sandboxed Domain",
               hostEvidence,
               ads,
               pset,
               null);   // Optionally: GetStrongName(Assembly.GetExecutingAssembly()));

            sandbox.ExecuteAssemblyByName("HelloWorld");
        }

        public static StrongName GetStrongName(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException("assembly");

            AssemblyName assemblyName = assembly.GetName();
            Debug.Assert(assemblyName != null, "Could not get assembly name");

            // Get the public key blob.
            byte[] publicKey = assemblyName.GetPublicKey();
            if (publicKey == null || publicKey.Length == 0)
                throw new InvalidOperationException("Assembly is not strongly named");

            StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);

            // Return the strong name.
            return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
        }

    }
}

См. также

Ссылки

SecurityAction

FileIOPermission

UIPermission

Основные понятия

Расширение метаданных с помощью атрибутов

Запрос разрешений

Управление доступом для кода